fields.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. from __future__ import unicode_literals
  2. from collections import defaultdict
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.core import checks
  5. from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
  6. from django.db import DEFAULT_DB_ALIAS, models, router, transaction
  7. from django.db.models import DO_NOTHING, signals
  8. from django.db.models.base import ModelBase, make_foreign_order_accessors
  9. from django.db.models.fields.related import (
  10. ForeignObject, ForeignObjectRel, ReverseManyToOneDescriptor,
  11. lazy_related_operation,
  12. )
  13. from django.db.models.query_utils import PathInfo
  14. from django.utils.encoding import python_2_unicode_compatible, smart_text
  15. from django.utils.functional import cached_property
  16. @python_2_unicode_compatible
  17. class GenericForeignKey(object):
  18. """
  19. Provide a generic many-to-one relation through the ``content_type`` and
  20. ``object_id`` fields.
  21. This class also doubles as an accessor to the related object (similar to
  22. ForwardManyToOneDescriptor) by adding itself as a model attribute.
  23. """
  24. # Field flags
  25. auto_created = False
  26. concrete = False
  27. editable = False
  28. hidden = False
  29. is_relation = True
  30. many_to_many = False
  31. many_to_one = True
  32. one_to_many = False
  33. one_to_one = False
  34. related_model = None
  35. remote_field = None
  36. def __init__(self, ct_field='content_type', fk_field='object_id', for_concrete_model=True):
  37. self.ct_field = ct_field
  38. self.fk_field = fk_field
  39. self.for_concrete_model = for_concrete_model
  40. self.editable = False
  41. self.rel = None
  42. self.column = None
  43. def contribute_to_class(self, cls, name, **kwargs):
  44. self.name = name
  45. self.model = cls
  46. self.cache_attr = "_%s_cache" % name
  47. cls._meta.add_field(self, virtual=True)
  48. # Only run pre-initialization field assignment on non-abstract models
  49. if not cls._meta.abstract:
  50. signals.pre_init.connect(self.instance_pre_init, sender=cls)
  51. setattr(cls, name, self)
  52. def get_filter_kwargs_for_object(self, obj):
  53. """See corresponding method on Field"""
  54. return {
  55. self.fk_field: getattr(obj, self.fk_field),
  56. self.ct_field: getattr(obj, self.ct_field),
  57. }
  58. def get_forward_related_filter(self, obj):
  59. """See corresponding method on RelatedField"""
  60. return {
  61. self.fk_field: obj.pk,
  62. self.ct_field: ContentType.objects.get_for_model(obj).pk,
  63. }
  64. def __str__(self):
  65. model = self.model
  66. app = model._meta.app_label
  67. return '%s.%s.%s' % (app, model._meta.object_name, self.name)
  68. def check(self, **kwargs):
  69. errors = []
  70. errors.extend(self._check_field_name())
  71. errors.extend(self._check_object_id_field())
  72. errors.extend(self._check_content_type_field())
  73. return errors
  74. def _check_field_name(self):
  75. if self.name.endswith("_"):
  76. return [
  77. checks.Error(
  78. 'Field names must not end with an underscore.',
  79. obj=self,
  80. id='fields.E001',
  81. )
  82. ]
  83. else:
  84. return []
  85. def _check_object_id_field(self):
  86. try:
  87. self.model._meta.get_field(self.fk_field)
  88. except FieldDoesNotExist:
  89. return [
  90. checks.Error(
  91. "The GenericForeignKey object ID references the non-existent field '%s'." % self.fk_field,
  92. obj=self,
  93. id='contenttypes.E001',
  94. )
  95. ]
  96. else:
  97. return []
  98. def _check_content_type_field(self):
  99. """
  100. Check if field named `field_name` in model `model` exists and is a
  101. valid content_type field (is a ForeignKey to ContentType).
  102. """
  103. try:
  104. field = self.model._meta.get_field(self.ct_field)
  105. except FieldDoesNotExist:
  106. return [
  107. checks.Error(
  108. "The GenericForeignKey content type references the non-existent field '%s.%s'." % (
  109. self.model._meta.object_name, self.ct_field
  110. ),
  111. obj=self,
  112. id='contenttypes.E002',
  113. )
  114. ]
  115. else:
  116. if not isinstance(field, models.ForeignKey):
  117. return [
  118. checks.Error(
  119. "'%s.%s' is not a ForeignKey." % (
  120. self.model._meta.object_name, self.ct_field
  121. ),
  122. hint=(
  123. "GenericForeignKeys must use a ForeignKey to "
  124. "'contenttypes.ContentType' as the 'content_type' field."
  125. ),
  126. obj=self,
  127. id='contenttypes.E003',
  128. )
  129. ]
  130. elif field.remote_field.model != ContentType:
  131. return [
  132. checks.Error(
  133. "'%s.%s' is not a ForeignKey to 'contenttypes.ContentType'." % (
  134. self.model._meta.object_name, self.ct_field
  135. ),
  136. hint=(
  137. "GenericForeignKeys must use a ForeignKey to "
  138. "'contenttypes.ContentType' as the 'content_type' field."
  139. ),
  140. obj=self,
  141. id='contenttypes.E004',
  142. )
  143. ]
  144. else:
  145. return []
  146. def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs):
  147. """
  148. Handle initializing an object with the generic FK instead of
  149. content_type and object_id fields.
  150. """
  151. if self.name in kwargs:
  152. value = kwargs.pop(self.name)
  153. if value is not None:
  154. kwargs[self.ct_field] = self.get_content_type(obj=value)
  155. kwargs[self.fk_field] = value._get_pk_val()
  156. else:
  157. kwargs[self.ct_field] = None
  158. kwargs[self.fk_field] = None
  159. def get_content_type(self, obj=None, id=None, using=None):
  160. if obj is not None:
  161. return ContentType.objects.db_manager(obj._state.db).get_for_model(
  162. obj, for_concrete_model=self.for_concrete_model)
  163. elif id is not None:
  164. return ContentType.objects.db_manager(using).get_for_id(id)
  165. else:
  166. # This should never happen. I love comments like this, don't you?
  167. raise Exception("Impossible arguments to GFK.get_content_type!")
  168. def get_prefetch_queryset(self, instances, queryset=None):
  169. if queryset is not None:
  170. raise ValueError("Custom queryset can't be used for this lookup.")
  171. # For efficiency, group the instances by content type and then do one
  172. # query per model
  173. fk_dict = defaultdict(set)
  174. # We need one instance for each group in order to get the right db:
  175. instance_dict = {}
  176. ct_attname = self.model._meta.get_field(self.ct_field).get_attname()
  177. for instance in instances:
  178. # We avoid looking for values if either ct_id or fkey value is None
  179. ct_id = getattr(instance, ct_attname)
  180. if ct_id is not None:
  181. fk_val = getattr(instance, self.fk_field)
  182. if fk_val is not None:
  183. fk_dict[ct_id].add(fk_val)
  184. instance_dict[ct_id] = instance
  185. ret_val = []
  186. for ct_id, fkeys in fk_dict.items():
  187. instance = instance_dict[ct_id]
  188. ct = self.get_content_type(id=ct_id, using=instance._state.db)
  189. ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys))
  190. # For doing the join in Python, we have to match both the FK val and the
  191. # content type, so we use a callable that returns a (fk, class) pair.
  192. def gfk_key(obj):
  193. ct_id = getattr(obj, ct_attname)
  194. if ct_id is None:
  195. return None
  196. else:
  197. model = self.get_content_type(id=ct_id,
  198. using=obj._state.db).model_class()
  199. return (model._meta.pk.get_prep_value(getattr(obj, self.fk_field)),
  200. model)
  201. return (ret_val,
  202. lambda obj: (obj._get_pk_val(), obj.__class__),
  203. gfk_key,
  204. True,
  205. self.cache_attr)
  206. def is_cached(self, instance):
  207. return hasattr(instance, self.cache_attr)
  208. def __get__(self, instance, cls=None):
  209. if instance is None:
  210. return self
  211. try:
  212. return getattr(instance, self.cache_attr)
  213. except AttributeError:
  214. rel_obj = None
  215. # Make sure to use ContentType.objects.get_for_id() to ensure that
  216. # lookups are cached (see ticket #5570). This takes more code than
  217. # the naive ``getattr(instance, self.ct_field)``, but has better
  218. # performance when dealing with GFKs in loops and such.
  219. f = self.model._meta.get_field(self.ct_field)
  220. ct_id = getattr(instance, f.get_attname(), None)
  221. if ct_id is not None:
  222. ct = self.get_content_type(id=ct_id, using=instance._state.db)
  223. try:
  224. rel_obj = ct.get_object_for_this_type(pk=getattr(instance, self.fk_field))
  225. except ObjectDoesNotExist:
  226. pass
  227. setattr(instance, self.cache_attr, rel_obj)
  228. return rel_obj
  229. def __set__(self, instance, value):
  230. ct = None
  231. fk = None
  232. if value is not None:
  233. ct = self.get_content_type(obj=value)
  234. fk = value._get_pk_val()
  235. setattr(instance, self.ct_field, ct)
  236. setattr(instance, self.fk_field, fk)
  237. setattr(instance, self.cache_attr, value)
  238. class GenericRel(ForeignObjectRel):
  239. """
  240. Used by GenericRelation to store information about the relation.
  241. """
  242. def __init__(self, field, to, related_name=None, related_query_name=None, limit_choices_to=None):
  243. super(GenericRel, self).__init__(
  244. field, to,
  245. related_name=related_query_name or '+',
  246. related_query_name=related_query_name,
  247. limit_choices_to=limit_choices_to,
  248. on_delete=DO_NOTHING,
  249. )
  250. class GenericRelation(ForeignObject):
  251. """
  252. Provide a reverse to a relation created by a GenericForeignKey.
  253. """
  254. # Field flags
  255. auto_created = False
  256. many_to_many = False
  257. many_to_one = False
  258. one_to_many = True
  259. one_to_one = False
  260. rel_class = GenericRel
  261. def __init__(self, to, object_id_field='object_id', content_type_field='content_type',
  262. for_concrete_model=True, related_query_name=None, limit_choices_to=None, **kwargs):
  263. kwargs['rel'] = self.rel_class(
  264. self, to,
  265. related_query_name=related_query_name,
  266. limit_choices_to=limit_choices_to,
  267. )
  268. kwargs['blank'] = True
  269. kwargs['on_delete'] = models.CASCADE
  270. kwargs['editable'] = False
  271. kwargs['serialize'] = False
  272. # This construct is somewhat of an abuse of ForeignObject. This field
  273. # represents a relation from pk to object_id field. But, this relation
  274. # isn't direct, the join is generated reverse along foreign key. So,
  275. # the from_field is object_id field, to_field is pk because of the
  276. # reverse join.
  277. super(GenericRelation, self).__init__(
  278. to, from_fields=[object_id_field], to_fields=[], **kwargs)
  279. self.object_id_field_name = object_id_field
  280. self.content_type_field_name = content_type_field
  281. self.for_concrete_model = for_concrete_model
  282. def check(self, **kwargs):
  283. errors = super(GenericRelation, self).check(**kwargs)
  284. errors.extend(self._check_generic_foreign_key_existence())
  285. return errors
  286. def _check_generic_foreign_key_existence(self):
  287. target = self.remote_field.model
  288. if isinstance(target, ModelBase):
  289. fields = target._meta.virtual_fields
  290. if any(isinstance(field, GenericForeignKey) and
  291. field.ct_field == self.content_type_field_name and
  292. field.fk_field == self.object_id_field_name
  293. for field in fields):
  294. return []
  295. else:
  296. return [
  297. checks.Error(
  298. "The GenericRelation defines a relation with the model "
  299. "'%s.%s', but that model does not have a GenericForeignKey." % (
  300. target._meta.app_label, target._meta.object_name
  301. ),
  302. obj=self,
  303. id='contenttypes.E004',
  304. )
  305. ]
  306. else:
  307. return []
  308. def resolve_related_fields(self):
  309. self.to_fields = [self.model._meta.pk.name]
  310. return [(self.remote_field.model._meta.get_field(self.object_id_field_name), self.model._meta.pk)]
  311. def _get_path_info_with_parent(self):
  312. """
  313. Return the path that joins the current model through any parent models.
  314. The idea is that if you have a GFK defined on a parent model then we
  315. need to join the parent model first, then the child model.
  316. """
  317. # With an inheritance chain ChildTag -> Tag and Tag defines the
  318. # GenericForeignKey, and a TaggedItem model has a GenericRelation to
  319. # ChildTag, then we need to generate a join from TaggedItem to Tag
  320. # (as Tag.object_id == TaggedItem.pk), and another join from Tag to
  321. # ChildTag (as that is where the relation is to). Do this by first
  322. # generating a join to the parent model, then generating joins to the
  323. # child models.
  324. path = []
  325. opts = self.remote_field.model._meta
  326. parent_opts = opts.get_field(self.object_id_field_name).model._meta
  327. target = parent_opts.pk
  328. path.append(PathInfo(self.model._meta, parent_opts, (target,), self.remote_field, True, False))
  329. # Collect joins needed for the parent -> child chain. This is easiest
  330. # to do if we collect joins for the child -> parent chain and then
  331. # reverse the direction (call to reverse() and use of
  332. # field.remote_field.get_path_info()).
  333. parent_field_chain = []
  334. while parent_opts != opts:
  335. field = opts.get_ancestor_link(parent_opts.model)
  336. parent_field_chain.append(field)
  337. opts = field.remote_field.model._meta
  338. parent_field_chain.reverse()
  339. for field in parent_field_chain:
  340. path.extend(field.remote_field.get_path_info())
  341. return path
  342. def get_path_info(self):
  343. opts = self.remote_field.model._meta
  344. object_id_field = opts.get_field(self.object_id_field_name)
  345. if object_id_field.model != opts.model:
  346. return self._get_path_info_with_parent()
  347. else:
  348. target = opts.pk
  349. return [PathInfo(self.model._meta, opts, (target,), self.remote_field, True, False)]
  350. def get_reverse_path_info(self):
  351. opts = self.model._meta
  352. from_opts = self.remote_field.model._meta
  353. return [PathInfo(from_opts, opts, (opts.pk,), self, not self.unique, False)]
  354. def get_choices_default(self):
  355. return super(GenericRelation, self).get_choices(include_blank=False)
  356. def value_to_string(self, obj):
  357. qs = getattr(obj, self.name).all()
  358. return smart_text([instance._get_pk_val() for instance in qs])
  359. def contribute_to_class(self, cls, name, **kwargs):
  360. kwargs['virtual_only'] = True
  361. super(GenericRelation, self).contribute_to_class(cls, name, **kwargs)
  362. self.model = cls
  363. setattr(cls, self.name, ReverseGenericManyToOneDescriptor(self.remote_field))
  364. # Add get_RELATED_order() and set_RELATED_order() methods if the model
  365. # on the other end of this relation is ordered with respect to this.
  366. def matching_gfk(field):
  367. return (
  368. isinstance(field, GenericForeignKey) and
  369. self.content_type_field_name == field.ct_field and
  370. self.object_id_field_name == field.fk_field
  371. )
  372. def make_generic_foreign_order_accessors(related_model, model):
  373. if matching_gfk(model._meta.order_with_respect_to):
  374. make_foreign_order_accessors(model, related_model)
  375. lazy_related_operation(make_generic_foreign_order_accessors, self.model, self.remote_field.model)
  376. def set_attributes_from_rel(self):
  377. pass
  378. def get_internal_type(self):
  379. return "ManyToManyField"
  380. def get_content_type(self):
  381. """
  382. Return the content type associated with this field's model.
  383. """
  384. return ContentType.objects.get_for_model(self.model,
  385. for_concrete_model=self.for_concrete_model)
  386. def get_extra_restriction(self, where_class, alias, remote_alias):
  387. field = self.remote_field.model._meta.get_field(self.content_type_field_name)
  388. contenttype_pk = self.get_content_type().pk
  389. cond = where_class()
  390. lookup = field.get_lookup('exact')(field.get_col(remote_alias), contenttype_pk)
  391. cond.add(lookup, 'AND')
  392. return cond
  393. def bulk_related_objects(self, objs, using=DEFAULT_DB_ALIAS):
  394. """
  395. Return all objects related to ``objs`` via this ``GenericRelation``.
  396. """
  397. return self.remote_field.model._base_manager.db_manager(using).filter(**{
  398. "%s__pk" % self.content_type_field_name: ContentType.objects.db_manager(using).get_for_model(
  399. self.model, for_concrete_model=self.for_concrete_model).pk,
  400. "%s__in" % self.object_id_field_name: [obj.pk for obj in objs]
  401. })
  402. class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor):
  403. """
  404. Accessor to the related objects manager on the one-to-many relation created
  405. by GenericRelation.
  406. In the example::
  407. class Post(Model):
  408. comments = GenericRelation(Comment)
  409. ``post.comments`` is a ReverseGenericManyToOneDescriptor instance.
  410. """
  411. @cached_property
  412. def related_manager_cls(self):
  413. return create_generic_related_manager(
  414. self.rel.model._default_manager.__class__,
  415. self.rel,
  416. )
  417. def create_generic_related_manager(superclass, rel):
  418. """
  419. Factory function to create a manager that subclasses another manager
  420. (generally the default manager of a given model) and adds behaviors
  421. specific to generic relations.
  422. """
  423. class GenericRelatedObjectManager(superclass):
  424. def __init__(self, instance=None):
  425. super(GenericRelatedObjectManager, self).__init__()
  426. self.instance = instance
  427. self.model = rel.model
  428. content_type = ContentType.objects.db_manager(instance._state.db).get_for_model(
  429. instance, for_concrete_model=rel.field.for_concrete_model)
  430. self.content_type = content_type
  431. self.content_type_field_name = rel.field.content_type_field_name
  432. self.object_id_field_name = rel.field.object_id_field_name
  433. self.prefetch_cache_name = rel.field.attname
  434. self.pk_val = instance._get_pk_val()
  435. self.core_filters = {
  436. '%s__pk' % self.content_type_field_name: content_type.id,
  437. self.object_id_field_name: self.pk_val,
  438. }
  439. def __call__(self, **kwargs):
  440. # We use **kwargs rather than a kwarg argument to enforce the
  441. # `manager='manager_name'` syntax.
  442. manager = getattr(self.model, kwargs.pop('manager'))
  443. manager_class = create_generic_related_manager(manager.__class__, rel)
  444. return manager_class(instance=self.instance)
  445. do_not_call_in_templates = True
  446. def __str__(self):
  447. return repr(self)
  448. def get_queryset(self):
  449. try:
  450. return self.instance._prefetched_objects_cache[self.prefetch_cache_name]
  451. except (AttributeError, KeyError):
  452. db = self._db or router.db_for_read(self.model, instance=self.instance)
  453. return super(GenericRelatedObjectManager, self).get_queryset().using(db).filter(**self.core_filters)
  454. def get_prefetch_queryset(self, instances, queryset=None):
  455. if queryset is None:
  456. queryset = super(GenericRelatedObjectManager, self).get_queryset()
  457. queryset._add_hints(instance=instances[0])
  458. queryset = queryset.using(queryset._db or self._db)
  459. query = {
  460. '%s__pk' % self.content_type_field_name: self.content_type.id,
  461. '%s__in' % self.object_id_field_name: set(obj._get_pk_val() for obj in instances)
  462. }
  463. # We (possibly) need to convert object IDs to the type of the
  464. # instances' PK in order to match up instances:
  465. object_id_converter = instances[0]._meta.pk.to_python
  466. return (queryset.filter(**query),
  467. lambda relobj: object_id_converter(getattr(relobj, self.object_id_field_name)),
  468. lambda obj: obj._get_pk_val(),
  469. False,
  470. self.prefetch_cache_name)
  471. def add(self, *objs, **kwargs):
  472. bulk = kwargs.pop('bulk', True)
  473. db = router.db_for_write(self.model, instance=self.instance)
  474. def check_and_update_obj(obj):
  475. if not isinstance(obj, self.model):
  476. raise TypeError("'%s' instance expected, got %r" % (
  477. self.model._meta.object_name, obj
  478. ))
  479. setattr(obj, self.content_type_field_name, self.content_type)
  480. setattr(obj, self.object_id_field_name, self.pk_val)
  481. if bulk:
  482. pks = []
  483. for obj in objs:
  484. if obj._state.adding or obj._state.db != db:
  485. raise ValueError(
  486. "%r instance isn't saved. Use bulk=False or save "
  487. "the object first. but must be." % obj
  488. )
  489. check_and_update_obj(obj)
  490. pks.append(obj.pk)
  491. self.model._base_manager.using(db).filter(pk__in=pks).update(**{
  492. self.content_type_field_name: self.content_type,
  493. self.object_id_field_name: self.pk_val,
  494. })
  495. else:
  496. with transaction.atomic(using=db, savepoint=False):
  497. for obj in objs:
  498. check_and_update_obj(obj)
  499. obj.save()
  500. add.alters_data = True
  501. def remove(self, *objs, **kwargs):
  502. if not objs:
  503. return
  504. bulk = kwargs.pop('bulk', True)
  505. self._clear(self.filter(pk__in=[o.pk for o in objs]), bulk)
  506. remove.alters_data = True
  507. def clear(self, **kwargs):
  508. bulk = kwargs.pop('bulk', True)
  509. self._clear(self, bulk)
  510. clear.alters_data = True
  511. def _clear(self, queryset, bulk):
  512. db = router.db_for_write(self.model, instance=self.instance)
  513. queryset = queryset.using(db)
  514. if bulk:
  515. # `QuerySet.delete()` creates its own atomic block which
  516. # contains the `pre_delete` and `post_delete` signal handlers.
  517. queryset.delete()
  518. else:
  519. with transaction.atomic(using=db, savepoint=False):
  520. for obj in queryset:
  521. obj.delete()
  522. _clear.alters_data = True
  523. def set(self, objs, **kwargs):
  524. # Force evaluation of `objs` in case it's a queryset whose value
  525. # could be affected by `manager.clear()`. Refs #19816.
  526. objs = tuple(objs)
  527. bulk = kwargs.pop('bulk', True)
  528. clear = kwargs.pop('clear', False)
  529. db = router.db_for_write(self.model, instance=self.instance)
  530. with transaction.atomic(using=db, savepoint=False):
  531. if clear:
  532. self.clear()
  533. self.add(*objs, bulk=bulk)
  534. else:
  535. old_objs = set(self.using(db).all())
  536. new_objs = []
  537. for obj in objs:
  538. if obj in old_objs:
  539. old_objs.remove(obj)
  540. else:
  541. new_objs.append(obj)
  542. self.remove(*old_objs)
  543. self.add(*new_objs, bulk=bulk)
  544. set.alters_data = True
  545. def create(self, **kwargs):
  546. kwargs[self.content_type_field_name] = self.content_type
  547. kwargs[self.object_id_field_name] = self.pk_val
  548. db = router.db_for_write(self.model, instance=self.instance)
  549. return super(GenericRelatedObjectManager, self).using(db).create(**kwargs)
  550. create.alters_data = True
  551. def get_or_create(self, **kwargs):
  552. kwargs[self.content_type_field_name] = self.content_type
  553. kwargs[self.object_id_field_name] = self.pk_val
  554. db = router.db_for_write(self.model, instance=self.instance)
  555. return super(GenericRelatedObjectManager, self).using(db).get_or_create(**kwargs)
  556. get_or_create.alters_data = True
  557. def update_or_create(self, **kwargs):
  558. kwargs[self.content_type_field_name] = self.content_type
  559. kwargs[self.object_id_field_name] = self.pk_val
  560. db = router.db_for_write(self.model, instance=self.instance)
  561. return super(GenericRelatedObjectManager, self).using(db).update_or_create(**kwargs)
  562. update_or_create.alters_data = True
  563. return GenericRelatedObjectManager