0

So, I am building a Store website, I got 2 apps, one app called Store, it has two models "Store" and "UnitStore". The second app is called Product whereas it got single models called Store.

In Product admin, I am using a formfield_for_foreignkey method to show StoreUnit and Store like this: "Store_name | Unit_name"

So, my problem is that when I try to create a product, it always ask for a UnitStore's foreign key, but not all products comes from a UnitStore, some product can only be found in a Store, therefore, I am not able to create a instance.

- Store > Models.py 

class Store(models.Model):

    store_name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.store_name 

class UnitStore(models.Model):

    store_unit_name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    store = models.ForeignKey(
        Store,
        related_name='units',
        on_delete=models.CASCADE,
    )

    def __str__(self):
        return self.store_unit_name 


Product > Models.py

class Product(models.Model):

    product= models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    store_unit_name = models.ForeignKey(
        StoreUnit,
        related_name='units',
        on_delete=models.CASCADE,
    )

    def __str__(self):
        return self.product

- Product > Admin.py

class CustomProduct(admin.ModelAdmin):
    model = Product
    list_display = ('product', 'created_at', 'aupdated_at',
                    'store_unit_name',)
    list_select_related = ('store_unit_name')
    fieldsets = (
        ("Prodcut's Name:", {
            'fields': ('product',)}),
        ('Store:', {
            'fields': ('store_unit_name',)}),  
    )

    def save_model(self, request, obj, form, change):
        obj.created_by = request.user
        super().save_model(request, obj, form, change)

Should I add another foreign key to the Product models, like the example below. therefore I should be able to access the Product by: product.store.store_name.

class Product(models.Model):

    product= models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    store_unit_name = models.ForeignKey(
        StoreUnit,
        related_name='units',
        on_delete=models.CASCADE,
    )
  store= models.ForeignKey(
        Store,
        related_name='stores',
        on_delete=models.CASCADE,
    )
Joanny
  • 15
  • 1
  • 5
  • Is the UnitStore class in the example actually supposed to be StoreUnit? If not, could you please share the StoreUnit model – Mikey Lockwood May 01 '19 at 12:37
  • Hello there, thanks for reaching out! Well, so, both Store and UnitStore belongs to the Store Models. – Joanny May 01 '19 at 16:51

1 Answers1

0

You need to have a Store model that captures both stores and unit stores and its __str__ method should print the main store name always and the unit store name if applicable:

class Store(models.Model):

    store_name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    main_store = models.ForeignKey(
        'Store',
        null=True,
        related_name='units',
        on_delete=models.CASCADE,
    )

    def __str__(self):
        ret_value = self.main_store.store_name + " | " if self.main_store else ""
        return ret_value + self.store_name

Once you have the model like this you can just have a single foreign key pointing at either a store or a unit store.

class Product(models.Model):

    product = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    store= models.ForeignKey(
        Store,
        related_name='products',
        on_delete=models.CASCADE,
    )
Daniele Bernardini
  • 1,516
  • 1
  • 12
  • 29
  • Hello there, thanks for reaching out! I thought so too, but the problem is that, in Product admin, I am using a formfield_for_foreignkey method to override the “store_unit_name” field to show the Unit name like this: "Store_name | Unit_name", i.e: “Store One | NYC Unit”. I through about adding the attribute null=True to the Product > store foreign key, therefore, in Product > Admin.py, I can add both field to fieldsets: "store_unit_name" and "store", and finally, if the product comes from a Unit Store I select "store_unit_name", otherwise select "store". – Joanny May 01 '19 at 16:49
  • If you want to change the way store units are displayed in the admin forms just implement `__str__()` method in `UnitStore` model. https://docs.djangoproject.com/en/2.2/ref/models/instances/#str You don't need a custom form field. – Daniele Bernardini May 01 '19 at 16:54
  • Absolutely, I know that, but unfortunately that doesn't solve my problem, I mean, not all products comes from a UnitStore models, some comes from a Store who doesn't have a UnitStore. So, how do I get about to show the Store name, when I don't have a UnitStore, right now in the admin forms I am using "obj.store.store_name " – Joanny May 01 '19 at 17:32
  • So, what if I add another foreign key to the Product models, like the example above: but isn't that too much query? – Joanny May 01 '19 at 18:05
  • I think you need to change your model if that is the case. May I suggest to normalize the models and instead of having a `Store` and a `UnitStore`, just having a `Store`, with a nullable reference to a parent `Store`. All stores with a parent are the unit_store and in the `__str__` of the store you can output the name or the main store and the name of the unit store. – Daniele Bernardini May 01 '19 at 18:48
  • I see, will one Store be able to have more than one Unit? That is why I went with two Models, Store and Unit. – Joanny May 01 '19 at 20:13
  • Of course you just add as many units as you want, just set main_store to the same store – Daniele Bernardini May 01 '19 at 21:09