Как перенаправить на форму после анализа загруженного файла CSV, если элементы не существуют в базе данных? - PullRequest
0 голосов
/ 14 февраля 2019

У меня возникла проблема, которую я пытался решить в течение нескольких дней, и чувствую, что столкнулся с препятствием и не могу найти ответы на свои вопросы.То, что я пытаюсь сделать, это:

  1. Загрузить файл CSV (этот файл в основном содержит информацию о торгах акциями), который будет сохранен в таблице и сохранен в медиа-каталоге, содержимоезатем проанализировали и передали в словарь (этот шаг работает) - содержимое этого файла будет использоваться для обновления различных таблиц в моей базе данных позже.

  2. Когда я зацикливаюсь на ключе, пары значений в словаре проверяют, существуют ли определенные значения в различных моделях, которые используются в качестве внешних ключей (эта часть также работает).Например, если сделка помечена с Фондом X, а фонд X не существует в моей таблице фондов, я перейду к форме для заполнения всех полей, необходимых для создания фонда X в моей базе данных

  3. Если значение отсутствует, я хочу отправить его в форму, которая затем позволит мне создать это значение в базе данных, чтобы я мог заполнить необходимые поля (эта часть частично работает, я могу перейти кформа для пропущенных данных, но я не могу сохранить входные данные этой формы в базу данных)

У меня есть файл 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 %}
...