Closed eddielu closed 10 months ago
Hi there, Just as a tip which i already using,
You are correct in observing that manually retyping all the fields inside service functions can be error-prone and lead to maintenance challenges as the model evolves. One approach to mitigate this is to use Django's built-in introspection capabilities to dynamically fetch the fields of the model.forexample by something like this :
def course_create(**kwargs) -> Course:
obj = Course(**kwargs)
obj.full_clean()
obj.save()
return obj
you can pass a dictionary with the field names and their corresponding values as keyword arguments, and it will work for models of varying sizes.
Hello @eddielu :wave:
Thanks for the good question!
And sorry for the late response.
I'd say, there are a couple of potential options for that problem:
model_update
here - https://github.com/HackSoftware/Django-Styleguide-Example/blob/master/styleguide_example/common/services.py#L9Now, this particular version of model_update
is rather hard to read, so here's the gist of it:
def some_create_service(data):
valid_model_fields = [
"field_1",
"field_2",
# ...
"field_20"
]
obj = SomeModel()
for valid_model_field in valid_model_fields:
if valid_model_field in data:
value = data[valid_model_field]
setattr(obj, valid_model_field, value)
obj.fulll_clean()
obj.save()
return obj
Now, data
can be a dictionary or a class or whatever you think it'd be suitable. My preference, most of the times, would be to use some @define
class, using attrs
You can take this approach and apply it like that:
def some_create_service(really_important_field_1, really_important_field_2, data):
...
And have the interface of the function / method specify things that are important (and usually required).
For example, if you have 20 fields, 3 of which are required & the rest are optional - I'd take this approach :+1:
Let me know if this answers your question :raised_hands:
Closing this for now. Feel free to reopen, in case you have additional questions.
Thanks for your help RadoRado. It seems like you are repeating field names in two separately places though (once on Model definition, and then another time by typing it out in valid_model_fields.
For example, let's say you need to add a new field21 to the model. You'd need to duplicate that name into valid_model_fields (in your example), otherwise you would never update field21.
It seems like the only option to avoid this repeat work is massooti's suggestion, right? I'm not fiercely opposed to doing repeat work, but I'm curious what your team does in production - do you typically just repeat the same name twice in your code?
@RadoRado
Thanks for this amazing style guide. I just started following.
Quick question: the examples used in this guide all have very tiny models with <=5 fields. In real life, it feels like most production models grow up to 20+ fields easily.
This is problematic since the guide seems to suggest that fields are retyped out for service functions. For example,
Is the recommendation really to type out all field names again inside service functions? It feels like this leads to cases where one makes a model change but forgets to add the parameter in service functions. Also it leads to obscenely long function definitions that are difficult to maintain.
I'm curious what you all have done here in your development. Thanks again. Wishing you blessings.