Got an answer on StackOverflow https://stackoverflow.com/questions/52878934/django-field-instances-overriding-each-others-arguments/52879102#52879102
I was linking to a mutable dict instead of copying it. That was a bit dumb. Cheers, Chris Routh From: ch...@routh.io To: "django-users" <django-users@googlegroups.com> Sent: Thursday, October 18, 2018 7:58:29 AM Subject: Field Instances overriding each others arguments Hi folks, I am testing and preparing a new Django package for using bleach with Text and Char fields in the Django ORM and with DRF. I've hit a bit of a roadblock with it however and it has made me take pause and wonder if I truly understand how a models fields are instantiated. Hopefully someone can clear this up. I am initialising the arguments for bleach by loading a default settings dict from django.conf.settings, and then checking a field_args parameter to see if any have been overridden for a specific field definition, like below. This is then used in the pre_save function to call bleach: class BleachedCharField(CharField): """ An enhanced CharField for sanitising input with the Python library, bleach. """ def __init__ ( self , *args , field_args= None, **kwargs): """ Initialize the BleachedCharField with default arguments, and update with called parameters. :param tags: (dict) optional bleach argument overrides, format matches BLEACHFIELDS defaults. :param args: extra args to pass to CharField __init__ :param kwargs: undefined args """ super (BleachedCharField , self ). __init__ (*args , **kwargs) self .args = settings.BLEACHFIELDS or None if field_args: if 'tags' in field_args: self .args[ 'tags' ] = field_args[ 'tags' ] if 'attributes' in field_args: self .args[ 'attributes' ] = field_args[ 'attributes' ] if 'styles' in field_args: self .args[ 'styles' ] = field_args[ 'styles' ] if 'protocols' in field_args: self .args[ 'protocols' ] = field_args[ 'protocols' ] if 'strip' in field_args: self .args[ 'strip' ] = field_args[ 'strip' ] if 'strip_comments' in field_args: self .args[ 'strip_comments' ] = field_args[ 'strip_comments' ] def pre_save ( self , model_instance , add): """ Clean text, update model and return cleaned text. :param model_instance: (obj) model instance :param add: default textfield parameter, unused :return : clean text as unicode """ bleached = clean( getattr (model_instance , self .attname) , ** self .args) setattr (model_instance , self .attname , bleached) return bleached The problem I am having is that the `self.field_args` value for all fields on a model seems to be the value of the last field loaded on the model. So for example on this model: class Writing(models.Model): """ Stores a single writing of a specific Form ( relation :model:`writings.WritingForm` ) and Category ( relation :model:`writings.Category` ). """ author = models.ForeignKey( settings.AUTH_USER_MODEL , on_delete =models.CASCADE , help_text =trans( "Author" ) ) title = BleachedCharField( max_length = 200 , help_text =trans( "Title" ) ) created = models.DateTimeField( auto_now_add = True, help_text =trans( "First created." ) ) edited = models.DateTimeField( auto_now_add = True, help_text =trans( "Last edited." ) ) description = BleachedTextField( blank = True, help_text =trans( "A short description of the writing to entice potential readers." ) ) body = BleachedTextField( field_args =settings.PERMISSIVE_BLEACHFIELDS , help_text =trans( "The body of the writing itself." ) ) writing_form = models.ForeignKey( WritingForm , on_delete =models.CASCADE , help_text =trans( "Primary writing form." ) ) category = models.ForeignKey( Category , on_delete =models.CASCADE , help_text =trans( "Writing form category" ) ) slug = models.SlugField( editable = False, help_text =trans( "URL and SEO friendly lower-cased string." ) , unique = True ) comments = GenericRelation(settings.COMMENT_MODEL) On this model the `body` field which is the last field on the model overrides the self.args of all the BleachCharField and BleachedTextField instances before it, so they all take the same parameters. Am I missing something on this? Is self.args not being added to the fields, but to the model instance instead? Is that why the last fields settings override all the field settings? How should I be doing this to avoid this issue? Cheers, Chris Routh -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [ mailto:django-users+unsubscr...@googlegroups.com | django-users+unsubscr...@googlegroups.com ] . To post to this group, send email to [ mailto:django-users@googlegroups.com | django-users@googlegroups.com ] . Visit this group at [ https://groups.google.com/group/django-users | https://groups.google.com/group/django-users ] . To view this discussion on the web visit [ https://groups.google.com/d/msgid/django-users/1363577083.40556.1539874709796.JavaMail.zimbra%40routh.io?utm_medium=email&utm_source=footer | https://groups.google.com/d/msgid/django-users/1363577083.40556.1539874709796.JavaMail.zimbra%40routh.io ] . For more options, visit [ https://groups.google.com/d/optout | https://groups.google.com/d/optout ] . -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/1905302289.40934.1539883085456.JavaMail.zimbra%40routh.io. For more options, visit https://groups.google.com/d/optout.