Home > Software engineering >  If statement in Django Model Fields
If statement in Django Model Fields

Time:12-20

I want to add these fields to my Store Model, but i wanna include logic that if Let's say WooCoomerce was chosen as a StoreType, i want Access_Token not to be Required. Also when i Choose either Shopify/Shopper i want Consumer_key and Consumer_secret not to be required. Do you have any idea how to get around that?

    StoreType = models.CharField(blank=True, choices=Storetypes.choices, max_length=12)
    Api_Url = models.CharField(blank=True)
    Access_Key = models.CharField(blank=True, max_length=100)
    Consumer_Key = models.CharField(blank=True, max_length=100)
    Consumer_Secret = models.CharField(blank=True, max_length=100)

CodePudding user response:

You can't make this type of logic on database layer. For this case you can move this logic to a classmathod of the model to satisfy the dry-pattern. Also set the fields to nullable in your model.

Something like so:

class YourClass(models.Model):
    store_type = models.CharField(blank=True, choices=Storetypes.choices, max_length=12)
    api_url = models.CharField(blank=True,)
    access_key = models.CharField(blank=True, max_length=100, null=True)
    consumer_key = models.CharField(blank=True, max_length=100, null=True)
    consumer_secret = models.CharField(blank=True, max_length=100, null=True)

    @classmethod
    def save_woo_commerce(cls, api_url, consumer_key, consumer_secret):
        return YourClass.objects.create(
            store_type="woo_commerce",
            api_url=api_url,
            consumer_key=consumer_key,
            consumer_secret=consumer_secret
        )

    @classmethod
    def save_shopify(cls, api_url, access_key):
        return YourClass.objects.create(
            store_type="shopify",
            access_key=access_key,
            api_url=api_url,
        )

With that your logic is still connected to the model and you can reuse instance creation on multiple places of your code.

CodePudding user response:

At some point those fields are going to be inputs.

If they come in through a form, it's a matter of using a clean method that generates errors for invalid combinations, or checking at the view level. A pattern I have found myself using quite often with class-based views (based on FormView) is like the following. Key points: form.add_error to convert a valid form into an invalid one, and return self.form_invalid(form) to show the user what needs to be fixed.

def form_valid( self, form)
    store_type = form.Cleaned_data['store_type']
    api_url = form.cleaned_data[' ... ']
    ...
    # now, further checks
    ...
    errors = False
    if store_type == SHOPIFY or store_type == SHOPPER:
         # consumer_key and consumer secret not required
         consumer_key = consumer_secret = ''
         # but presumably, api_url and access_key are mandatory
         if api_url == '':
             # get human representation of store_type
             human_store_type = ...
             form.add_error('api_url', f'API Url is required whenever store type is "{human_store_type}"' ) 
             errors = True
         if access_key == '':
             ... # similar, but add error to access_Key field

         # maybe validate that the api_url and access_key actually work
         # and add an error if they don't work together?
         if not check_valid( api_url, access_key):
             errors = True
             form.add_error( None, 'api_url and access_key do not work with each other') # non-field error

         if errors:
             return self.form_invalid( form)

    elif store_type == ...
        ...

    # OK we have a completely valid set of inputs
    # get the object (if its a ModelForm)
    store  = form.save( commit = False)
    store.api_url = api_url
    ... # and the other fields we extra-validated
    store.save()

    return redirect( ...)

It's possible to subclass the save method on your object to cause an exception if any mandatory fields are blank, but this can be more trouble than its worth. If there is one or few views through which these fields can be set, then check there. Sometimes, it's even useful to save an incomplete object: give it a Boolean is_complete field. For example, it may be necessary for a human supervisor to authorize the addition of a new store.

  • Related