简体   繁体   中英

How to implement unique together in Django

im working on a sales team project where i'm trying to implement a function to upload their daily visit plan. While uploading i want to put a validation that, if visit for one customer is already uploaded then for same another wouldn't be uploaded and would raise a error like" Visit plan for this customer already exists on this date". I have read some where that unique together would help me to validate but im not sure how to use unique together in View. please find the below codes for your reference and help. Thanks in advance

Model:

class BeatPlan(models.Model):
beat_id = models.CharField(unique=True, max_length=15, null=True)
beat_dealer = models.ForeignKey(Dealer, null=True, on_delete=models.SET_NULL)
beat_user = models.ForeignKey('account.CustomUser', null=True, on_delete=models.SET_NULL)
beat_stake_holder = models.ForeignKey(StakeHolder, null=True, on_delete=models.SET_NULL)
beat_date = models.DateField(null=True)
create_date = models.DateField(null=True)
beat_status = models.CharField(choices=(('Not visited', 'Not visited'), ('Visited', 'Visited')),
                               default='Not visited', max_length=40, null=True)
beat_location = models.CharField(max_length=200, null=True)
beat_type = models.CharField(choices=(('Not planned', 'Not planned'), ('Planned', 'Planned')), max_length=50,
                             null=True)
beat_reason = models.CharField(max_length=200, null=True)

class Meta:
    unique_together = ('beat_date', 'beat_dealer')

def __str__(self):
    return str(self.beat_user) + str(self.beat_dealer) + str(self.beat_date)

View:

def upload_beat(request):
global u_beat_dealer, beat_user_id, beat_date
template = "upload_beat.html"
data = BeatPlan.objects.all()
l_beat = BeatPlan.objects.last()
l_beat_id = l_beat.id
print(l_beat_id)
current_month = datetime.datetime.now().strftime('%h')
# prompt is a context variable that can have different values      depending on their context
prompt = {
    'order': 'Order of the CSV should be name, email, address,    phone, profile',
    'profiles': data
}
# GET request returns the value of the data with the specified key.
if request.method == "GET":
    return render(request, template, prompt)
csv_file = request.FILES['file']
# let's check if it is a csv file
if not csv_file.name.endswith('.csv'):
    messages.error(request, 'THIS IS NOT A CSV FILE')
data_set = csv_file.read().decode('UTF-8')
# setup a stream which is when we loop through each line we are able to handle a data in a stream
io_string = io.StringIO(data_set)
next(io_string)
for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    u_beat_user_id = column[0]
    u_beat_dealer = column[1]
    beat_date = column[2]
    print(u_beat_user_id)
    if StakeHolder.objects.filter(unique_id=u_beat_user_id).exists():
        user_id = StakeHolder.objects.get(unique_id=u_beat_user_id)
        beat_user_id = user_id.id
        if Dealer.objects.filter(dealer_code=u_beat_dealer).exists():
            dealer_id = Dealer.objects.get(dealer_code=u_beat_dealer)
            u_beat_dealer = dealer_id.id
            l_beat_id += 1
            u_beat_id = current_month + str(l_beat_id)
            newBeatPlan = BeatPlan(beat_id=u_beat_id, beat_dealer_id=u_beat_dealer,
                                   beat_stake_holder_id=beat_user_id,
                                   beat_date=beat_date)
            newBeatPlan.save()
            messages.success(request, ' Beat added')

        else:
            messages.error(request, 'Dealer id does not exists')
    else:
        messages.error(request, "Unique ID doesn't exists")

context = {'beat_user': beat_user_id, 'dealer_code': u_beat_dealer, 'visit_date': beat_date}
return render(request, template, context)

Template:

{% extends 'base.html' %}
{% load static %}

{% block content %}
<h3 style="margin-left: 10px">Upload Beat</h3>
<div class="row" style="margin-left: 5px">
    <div class="col-md-6">
        <hr>
        {{ order }}
        <form action="" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <label for="file1"> Upload a file</label>
            <input type="file" id="file1" name="file" required><br><br><br><br><br>
            <small>Only accepts CSV files</small>
            <button class="btn btn-primary if-error-not-found" type="submit" 
  name="submit">Upload</button>
            <a href="{% url 'beatplan' %}">
                <div class="btn btn-primary back-button">Back</div>
            </a>
        </form>
        <br>
        <br>
    </div>

unique_together validates the data that is saved on the database. However, you can still submit forms where those 2 fields are not unique and get an error on your backend. What you need to do is to handle that error manually. Django forms have a method add_error(field, error). However, as I see, you do not use them, so you can just add an error parameter while rendering your template. Manually check if the customer has an input for that date, and add that error without saving anything to your database. Must look like this.

context['error'] = false
if YourModel.objects.filter(fields1=field1, field2=field2).exists():
     # your code that does not save anything
     context['error'] = true
     return render(request, template, context)

And handle the error on your template however you want. unique_together will make sure that whatever you do, invalid data is not saved, so keep it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM