Home > Enterprise >  how to apply constraints on Django field within the instances associated with the user
how to apply constraints on Django field within the instances associated with the user

Time:02-15

I am making a todo app for practice, the functionality I want to achieve is that, when a user create a task,Only the time field should be unique about all of his tasks, I have done (unique=True) In the time field in model but that make it unique all over the database, but I want it to be unique only with the tasks associated with the user. the view is below:

@login_required(login_url='login')
def home(request):
    tasks = Task.objects.filter(name__username=request.user.username)

    form = TaskForm()
    if request.method == 'POST':
        form = TaskForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.name = request.user
            obj.save()
            return redirect('home')
        else:
            print(request.POST)
            print(request.user.username)
            messages.warning(request, 'Invalid Data!')
            return redirect('home')

    context = {'tasks' : tasks}
    return render(request, 'task/home.html', context)

task model:

class Task(models.Model):
    choices = (
        ('Completed', 'Completed'),
        ('In Complete', 'In Complete'),
    )
    name = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
    task = models.CharField(max_length=200, null=False, blank=False)
    time = models.TimeField(auto_now_add=False, blank=True)
    status = models.CharField(max_length=200, choices=choices, null=True, blank=False)
    
    def __str__(self):
        return self.task
    
    def get_task_author_profile(self):
        return reverse('profile')

as you can see, I want to show the task that the logged in user has added.

the form is:

class TaskForm(ModelForm):
    class Meta:
        model = Task
        fields = '__all__'
        exclude = ['name']

the functionality I talked about above, I tried to achieve through view:

@login_required(login_url='login')
def home(request):
    tasks = Task.objects.filter(name__username=request.user.username)
    time = []
    for task in tasks:
        time.append(task['time'])
    form = TaskForm()
    if request.method == 'POST':
        form = TaskForm(request.POST)
        if form.is_valid() and form.cleaned_data['time'] != time:
            obj = form.save(commit=False)
            obj.name = request.user
            obj.save()
            return redirect('home')
        else:
            print(request.POST)
            print(request.user.username)
            messages.warning(request, 'Invalid Data!')
            return redirect('home')

    context = {'tasks' : tasks}
    return render(request, 'task/home.html', context)

but that gave an error: TypeError: 'Task' object is not subscriptable
I know its not right, but how can I achieve it, does Django have anything that can provide such fuctionality?

CodePudding user response:

The problem is coming from here:

for task in tasks:
    time.append(task['time'])  #<--

Here if you want to use access time, you need to use task.time because task is an object.

Also need to fix another thing in your exisiting code to make it work, because time is a list:

if form.is_valid() and form.cleaned_data['time'] in time:  
#                                                ^^^

BTW, you don't need to make it that complicated, you can add Database level constraint from the model to make the times unique for a specific user. Also, use DateTime field for that. You can use unique_togather for that:

class Task(models.Model):
    choices = (
        ('Completed', 'Completed'),
        ('In Complete', 'In Complete'),
    )
    name = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
    task = models.CharField(max_length=200, null=False, blank=False)
    time = models.DateTimeField(auto_now_add=False, blank=True)
    status = models.CharField(max_length=200, choices=choices, null=True, blank=False)
    
    class Meta:
        unique_togather = ['name', 'time']
  • Related