У меня возникла проблема, которую я пытался решить в течение нескольких дней, и чувствую, что столкнулся с препятствием и не могу найти ответы на свои вопросы.То, что я пытаюсь сделать, это:
Загрузить файл CSV (этот файл в основном содержит информацию о торгах акциями), который будет сохранен в таблице и сохранен в медиа-каталоге, содержимоезатем проанализировали и передали в словарь (этот шаг работает) - содержимое этого файла будет использоваться для обновления различных таблиц в моей базе данных позже.
Когда я зацикливаюсь на ключе, пары значений в словаре проверяют, существуют ли определенные значения в различных моделях, которые используются в качестве внешних ключей (эта часть также работает).Например, если сделка помечена с Фондом X, а фонд X не существует в моей таблице фондов, я перейду к форме для заполнения всех полей, необходимых для создания фонда X в моей базе данных
Если значение отсутствует, я хочу отправить его в форму, которая затем позволит мне создать это значение в базе данных, чтобы я мог заполнить необходимые поля (эта часть частично работает, я могу перейти кформа для пропущенных данных, но я не могу сохранить входные данные этой формы в базу данных)
У меня есть файл utils.py, который будет содержать все мои классы или вспомогательные функциичтобы сделать это.
если я распечатываю fund_form.errors из моего файла views.py, я получаю следующее:
<ul class="errorlist"><li>fund_code<ul class="errorlist"><li>This field is required.</li></ul></li><li>fund_name<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
Пожалуйста, дайте мне знать, если вам нужна любая другая информация, с которой я боролсяна несколько дней.
models.py
class Funds(models.Model):
fund_code = models.CharField(max_length=10, primary_key=True)
fund_name = models.CharField(max_length=100, unique=True)
def __str__(self):
return self.fund_code + ' - ' + self.fund_name
class Trades(models.Model):
trade_date = models.DateField(default=timezone.now)
trade_file = models.FileField(upload_to='trades/')
user = models.ForeignKey(User, on_delete=models.PROTECT)
views.py
VALID_FILE_TYPES = ['csv']
def upload_trades(request):
if not request.user.is_authenticated:
return render(request, 'position_mgmt/login.html')
else:
form = UploadFileForm(request.POST or None, request.FILES or None)
if form.is_valid():
trades = form.save(commit=False)
trades.user = request.user
trades.trade_date = request.POST['trade_date']
trades.trade_file = request.FILES['trade_file']
file_type = trades.trade_file.url.split('.')[-1]
file_type = file_type.lower()
if file_type not in VALID_FILE_TYPES:
context = {
'trades': trades,
'form': form,
'error_message': 'File type must be .csv',
}
return render(request, 'position_mgmt/upload_trades.html', context)
trades.save()
trade_upload = ProcessUpload(trades.trade_file.name)
parsed_trades = trade_upload.parse_trades()
database_check = trade_upload.check_database(parsed_trades, request)
if database_check['fund_code']:
fund_form = CreateFundForm(request.POST or None)
database_check['form'] = fund_form
if request.method == 'POST':
if fund_form.is_valid():
fund = fund_form.save(commit=False)
fund.user = request.user
fund.fund_code = request.POST['fund_code']
fund.fund_name = request.POST['fund_name']
fund.save()
return render(request, 'position_mgmt/upload_trades.html', {'trades': trades})
return render(request, 'position_mgmt/positions_form.html', database_check)
return render(request, 'position_mgmt/trade_files.html', {'trades': trades})
context = {'form': form}
return render(request, 'position_mgmt/upload_trades.html', context)
forms.py
class UploadFileForm(forms.ModelForm):
class Meta:
model = Trades
fields = ['trade_date', 'trade_file']
class CreateFundForm(forms.ModelForm):
class Meta:
model = Funds
fields = ['fund_code', 'fund_name']
utils.py
class ProcessUpload:
"""
A class to upload and process trade files
Attributes
----------
name: str
name of the file that will be processed
Methods
-------
parse_trades()
imports csv file from the MEDIA_ROOT and returns a list of dictionaries of format:
[{:,:}, {:,:}......]
check_database()
...
"""
def __init__(self, name):
"""
:param name:
name of the csv file
"""
self.name = name
def parse_trades(self):
file_path = os.path.join(settings.MEDIA_ROOT, self.name)
with open(file_path) as f:
trade_file = csv.DictReader(f, restkey='tags')
return list(trade_file)
def check_database(self, trade_dict, request):
for each_trade in trade_dict:
for _key in each_trade:
if _key == 'fund_code':
if not Funds.objects.filter(fund_code=each_trade[_key]).exists():
return {'fund_code': each_trade[_key],
'error_message': 'fund {0} does not exist'.format(each_trade[_key])}
return None
upload_trades.html
{% extends 'position_mgmt/base2.html' %}
{% block title %}Upload{% endblock %}
{% block body %}
<body>
{% block sub_body %}
{% endblock %}
<br>
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<h3>Upload Trades</h3>
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'position_mgmt/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
{% endblock %}
form-template.html
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-4">{{ field.label_tag }}</label>
<div class="col-sm-8">{{ field }}</div>
</div>
{% endfor %}