1

I am working on a commerce app, (with django but very new to it) where a user can create a listing through a ModelForm called ListingForm that inherits from a Model called Listing.Here is the code for the the Listing model and ListingForm:


from django.contrib.auth.models import AbstractUser
from django.db import models

class Listing(models.Model):
   NAME_CHOICES = [ 
       ('Fashion', 'Fashion'),
       ('Toys','Toys'),
       ('Electronic','Electronics'),
       ('Home', 'Home'),
       ('Other', 'Other')
   ]
   import datetime
   title = models.CharField(max_length= 64)
   date_made = models.DateField(default= datetime.date.today())
   description = models.TextField()
   user = models.ForeignKey(User, to_field='username', on_delete=models.CASCADE, related_name='user_listings', null=True)
   starting_bid = models.DecimalField(decimal_places=2, max_digits=264, default=10.00)
   image_url = models.CharField(blank=True, max_length=1000)
   category = models.ForeignKey(Category, on_delete=models.CASCADE, to_field='name', related_name='category_listings', default=NAME_CHOICES[4][0])
   listing_category = models.CharField(max_length=12, choices=NAME_CHOICES, null=True, default=NAME_CHOICES[4][0])
   is_active = models.BooleanField(default=True)
   def __str__(self):
       return f'{self.title}' 

Here is the code for the ```ListingForm``:

from .models import Listing
from django.forms import ModelForm

class ListingForm(ModelForm):
    class Meta:
        model = Listing
        exclude = [
            'date_made',
            'user',
            'category',
            'is_active',
        ]

The Listingmodel also has foreignkeys to and within the models User,Category and Bid.

Here is the code for these models(same imports as those shown for Listing model):

class User(AbstractUser):
    def __str__(self):
        return f'{self.username} '



class Category(models.Model):
    NAME_CHOICES = [ 
        ('Fashion', 'Fashion'),
        ('Toys','Toys'),
        ('Electronic','Electronics'),
        ('Home', 'Home'),
        ('Other', 'Other')
    ]

    name = models.CharField(max_length=12, choices= NAME_CHOICES, unique=True)
    def __str__(self):
        return self.name

class Bid(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=256)
    listing = models.ForeignKey('Listing', on_delete=models.CASCADE, related_name='bid_listings', default=20.00)
    def __str__(self):
        return f'{self.value}'

I want the user to be able to create a listing through a function based view:

def create_listing(request):

    if request.method == 'POST':
        import datetime
        listing_form = ListingForm(request.POST)
        bid = request.POST['starting_bid']
        

        
        if listing_form.is_valid():
            listing_form.save(commit=False)
            listing_form.user = request.user
            listing_form.date_made = datetime.datetime.today()
            listing_form.is_active = True
            listing_form.save()
            Bid.objects.create(value=bid, listing=listing_form)
            return HttpResponse('Listing has been saved successfully!')
        
    else:
        listing_form = ListingForm()
        return render(request, 'auctions/createlisting.html',{
        'listing_form':listing_form
    })

Upon attempting to run py manage.py runserver in the terminal, I get an Integrity error at /createlisting.

This is the traceback:

Traceback (most recent call last):
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\ACER\Desktop\Projects\commerce\auctions\views.py", line 84, in create_listing
    listing_form.save()
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\models.py", line 548, in save
    self.instance.save()
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\base.py", line 806, in save
    self.save_base(
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\base.py", line 857, in save_base
    updated = self._save_table(
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\base.py", line 1000, in _save_table
    results = self._do_insert(
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\base.py", line 1041, in _do_insert
    return manager._insert(
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\query.py", line 1434, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\sql\compiler.py", line 1632, in execute_sql
    self.connection.ops.fetch_returned_insert_columns(
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\base\operations.py", line 205, in fetch_returned_insert_columns
    return cursor.fetchone()
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\utils.py", line 97, in inner
    with self:
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\ACER\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\utils.py", line 98, in inner
    return func(*args, **kwargs)
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
[10/May/2022 21:00:05] ←[35;1m"POST /createlisting HTTP/1.1" 500 135972←[0m

How do I resolve this error? I suspect it has something to do with the uniqueness of my ids in one of my models, or the lack thereof.

Braiam
  • 1
  • 11
  • 47
  • 78
Tanatswa
  • 21
  • 3
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community May 10 '22 at 19:57

1 Answers1

0

First, in your models.py, you can change the date_made from DateField to a DateTimeField so you can save the time that your listing have been created on without need to import the datetime library and to override iton your views when the form is submitted by adding an attribute which is the auto_now_add:

...

date_made = models.DateTimeField(auto_now_add=True)

this article might be helpful if you wanna look for the difference between The DateTimeField and the DateField

https://www.jafoor.com/post/django-datetimefield-datefield/

Secondly, in your views.py, you can simply grab your grid coming from post data in your form by using the cleaned_data method that comes with our form, and from it we can grab all the post data coming, and it would be more better if you put this inside the if listing_form.is_valid():

...

     if listing_form.is_valid():
        bid = listing_form.cleaned_data['starting_bid']

Read more about cleaned_data method here: What is the use of cleaned_data in Django

Thirdly, in your views.py, you gotta change the listing attribute in the Bid.objects.create() from listing_form to listing_form.instance, the instance here means the object that your form is posting instead of assigning the whole form and ofc it'll get you an error:

...

   Bid.objects.create(value=bid, listing=listing_form.instance)

Now let's talk about your problem. To solve it first you gotta assign an attribute to your category field in the Listing class in your models.py which is db_constraint and we'll set it to False:

...

       category = models.ForeignKey(Category, on_delete=models.CASCADE, to_field='name', related_name='category_listings', default=NAME_CHOICES[4][0], db_constraint=False)

then in your cmd type python manage.py makemigrations then python manage.py migrate to migrate this change in your database

Then, go and register your Category model in admin.py so you can create categories manually from the Admin panel to assign later in your form:

from .models import Category

admin.site.register(Category)

Then go and make your categories from your admin panel.

Last but not least go to your views.py, and we'll add the category of your Listing manually by grabbing the listing_category field from our form by the cleaned_data function and by this we will grab the category that have the same name as the listing_category:

from .models import  Listing, Bid, Category
...
   if listing_form.is_valid():
      ...
      listing_form.category = Category.objects.get(name=listing_form.cleaned_data['listing_category'])
      ...


  • If you got any other issue contact me on my discord: Ramy#8162
Braiam
  • 1
  • 11
  • 47
  • 78
Ramy Berrekia
  • 55
  • 1
  • 5
  • Works elagantly! however may I please know how I assign my own datetime value in the views.py using the auto_now_add=True method. Also, do you mind explaining how the db_constraint attribute works? How does it fix the problem? – Tanatswa May 11 '22 at 12:57
  • You dont need to assign the datetime value in views.py, it'll be added automatically, and for the **db_constraint** I personally don't know too much about it but you can google it! – Ramy Berrekia May 11 '22 at 16:27