Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Overriding get_or_create with models.py

I have a class in which I want to override the get_or_create method. Basically if my class doesn't store the answer I want it do some process to get the answer and it's not provided. The method is really a get_or_retrieve method. So here's the class:

class P4User(models.Model):
  user      = models.CharField(max_length=100, primary_key=True)
  fullname  = models.CharField(max_length=256)
  email     = models.EmailField()
  access    = models.DateField(auto_now_add=True)
  update    = models.DateField(auto_now_add=True)

  @classmethod
  def get_or_retrieve(self, username, auto_now_add=False):
    try:
        return self.get(user=username), False
    except self.model.DoesNotExist:
        import P4
        import datetime
        from django.db import connection, transaction, IntegrityError
        p4 = P4.P4().connect()
        kwargs = p4.run(("user", "-o", username))[0]
        p4.disconnect()
        params = dict( [(k.lower(),v) for k, v in kwargs.items()])        
        obj = self.model(**params)
        sid = transaction.savepoint()
        obj.save(force_insert=True)
        transaction.savepoint_commit(sid)
        return obj, True
    except IntegrityError, e:
        transaction.savepoint_rollback(sid)
        try:
            return self.get(**kwargs), False
        except self.model.DoesNotExist:
            raise e

  def __unicode__(self):
    return str(self.user) 

Now I completely admit that I have used the db/models/query.py as my starting point. My problem is this line.

obj = self.model(**params)

I am able to get the params but I haven't defined self.model. I don't understand what that needs to be and it's not intuitively obvious what value that should be. Even looking back at the query.py I can't figure this out. Can someone explain this to me? I would really like to understand it and fix my code.

Thanks

like image 582
rh0dium Avatar asked Dec 19 '25 00:12

rh0dium


1 Answers

get_or_create is a Manager method, that is you access it via model.objects - it is the manager class that has an attribute model. So maybe the easiest thing to do would be to create a custom Manager and put your method there.

However, fixing your code as it stands is easy. self.model is just the classname - that line is simply instantiating the class with the given parameters. So you could just do

obj = P4User(**params)

although this breaks if you subclass the model.

like image 92
Daniel Roseman Avatar answered Dec 21 '25 23:12

Daniel Roseman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!