djangosqlitemigrationmakemigrations

django.db.utils.OperationalError: no such table: store_product


When I run makemigrations error is occurred. Here is models.py

def unique_order_id():
    not_unique = True
    while not_unique:
        uo_id = random.randint(1000000000, 9999999999)
        if not Order.objects.filter(order_id=uo_id):
            not_unique = False
    return uo_id


class Product(models.Model):
    #product code, name, category, unit price, current stock
    product_code = models.IntegerField(unique=True)
    name = models.CharField(max_length=100)
    category = models.CharField(max_length=100)
    unit_price = models.FloatField()
    current_stock = models.IntegerField()
    
    def __str__(self):
        return self.name


class Order(models.Model):
    
    order_id = models.IntegerField(unique=True, 
                        default=unique_order_id)
    customer_name =  models.CharField(max_length=100)
    phone = models.CharField(max_length=14)
    email = models.EmailField()

    qr_code = models.ImageField(upload_to='qr_codes', blank=True)

    
    def __str__(self):
        return self.customer_name

    #override ths save method for creating qrcode based on fields on this model.
    def save(self, *args, **kwargs):
        qr_info = "Invoice No : "+ str(self.order_id)+" Name : "+self.customer_name +" Phone : "+str(self.phone)+ " Email : "+ self.email
        qrcode_img = qrcode.make(qr_info)
        #canvas = Image.new('RGB', (290, 290), 'white')
        canvas = Image.new('RGB', (qrcode_img.pixel_size, qrcode_img.pixel_size), 'white')
        canvas.paste(qrcode_img)
        fname = f'qr_code-{self.customer_name}.png'
        buffer = BytesIO()
        canvas.save(buffer,'PNG')
        self.qr_code.save(fname, File(buffer), save=False)
        canvas.close()
        super().save(*args, **kwargs)

class OrderItem(models.Model):
    
    qty = models.IntegerField(default=0)

    product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)

    #this will return total price of product(unit_price*quntity)
    @property
    def get_total(self):
        total = self.product.unit_price * self.qty
        return total

This is forms.py codes

class ItemSelectForm(forms.Form):
    p_name = forms.ChoiceField(label='Select Product',choices=list ((obj.product_code,obj.name) for obj in Product.objects.all()))   
    qty = forms.IntegerField()

    #function for checking product avaiability
    def clean_qty(self):
        data = self.cleaned_data['qty']
        product_code = self.cleaned_data['p_name']
        product = Product.objects.get(product_code = product_code)
        if data > product.current_stock:
            raise forms.ValidationError(('Insufficient Stock'), code='ins_stock')
        # Always return a value to use as the new cleaned data, even if
        # this method didn't change it.
        return data

This code works fine on my environment, but when i run this on another environment and run makamigrations this error shows up. After searching online, my understanding is, the p_name field in the form is causing the error, the query is running even before creating the table.

p_name = forms.ChoiceField(label='Select Product',choices=list ((obj.product_code,obj.name) for obj in Product.objects.all()))

How can i get out of this situation and solve the error !


Solution

  • You are executing a query when the p_name field on the ItemSelectForm is initialised, this initialisation happens when your application is parsed/loaded/started. Executing queries at start-up of your application is bad practice and in this case preventing you from running migrations as the query you are running is for a model that has not been migrated.

    Use a ModelChoiceField instead and pass it a queryset, this queryset will not be executed on start-up and should alleviate this issue

    class ItemSelectForm(forms.Form):
        product = forms.ModelChoiceField(Product.objects.all(), label='Select Product')  
        qty = forms.IntegerField()
    
        #function for checking product availability
        def clean_qty(self):
            data = self.cleaned_data['qty']
            product = self.cleaned_data['product']
            if data > product.current_stock:
                raise forms.ValidationError(('Insufficient Stock'), code='ins_stock')
            # Always return a value to use as the new cleaned data, even if
            # this method didn't change it.
            return data