/flexselect/Doc/README.markdown

https://github.com/DarioGT/ProtoLib · Markdown · 184 lines · 144 code · 40 blank · 0 comment · 0 complexity · 026b4b3b183d9226834239e23e05d003 MD5 · raw file

  1. ## About Django Admin FlexSelect ##
  2. FlexSelect is a small app for the Django Admin that makes it trivial to have
  3. foreign keys depend on each other. By depend I mean that choices and additional
  4. content of one field updates dynamically when another is changed.
  5. ## Usage example ##
  6. See the video at http://www.youtube.com/watch?v=ooii3iCTZ6o.
  7. In the following we will define a Case model with two foreign key fields, a
  8. base field `client` and a trigger field `company_contact_person`. When we
  9. change the client on the Case change view the company_contact_person updates
  10. accordingly. Furthermore we will display the customer_contact_persons company
  11. and email as additional details.
  12. In "models.py":
  13. ```python
  14. from django.db import models as m
  15. from django.core.exceptions import ValidationError
  16. """
  17. No changes to the models are needed to use flexselect.
  18. """
  19. class Company(m.Model):
  20. name = m.CharField(max_length=80)
  21. def __unicode__(self):
  22. return self.name
  23. class CompanyContactPerson(m.Model):
  24. company = m.ForeignKey(Company)
  25. name = m.CharField(max_length=80)
  26. email = m.EmailField()
  27. def __unicode__(self):
  28. return self.name
  29. class Client(m.Model):
  30. company = m.ForeignKey(Company)
  31. name = m.CharField(max_length=80)
  32. def __unicode__(self):
  33. return self.name
  34. class Case(m.Model):
  35. client = m.ForeignKey(Client)
  36. company_contact_person = m.ForeignKey(CompanyContactPerson)
  37. def clean(self):
  38. """
  39. Makes sure the company for client is the same as the company for the
  40. customer contact person. Note that you need to check for `None` too
  41. if the fields are not required.
  42. """
  43. if not self.client.company == self.company_contact_person.company:
  44. raise ValidationError('The clients and the contacts company does'
  45. ' not match.')
  46. def __unicode__(self):
  47. return u'Case: %d' % self.id
  48. ```
  49. In "admin.py":
  50. ```python
  51. from django.contrib import admin
  52. from flexselect import FlexSelectWidget
  53. from test_flexselect.tests.models import (Company, Case, Client,
  54. CompanyContactPerson,)
  55. class CompanyContactPersonWidget(FlexSelectWidget):
  56. """
  57. The widget must extend FlexSelectWidget and implement trigger_fields,
  58. details(), queryset() and empty_choices_text().
  59. """
  60. trigger_fields = ['client']
  61. """Fields which on change will update the base field."""
  62. def details(self, base_field_instance, instance):
  63. """
  64. HTML appended to the base_field.
  65. - base_field_instance: An instance of the base_field.
  66. - instance: A partial instance of the parent model loaded from the
  67. request.
  68. Returns a unicoded string.
  69. """
  70. return u"""\
  71. <div>
  72. <dl>
  73. <dt>%s</dt><dd>%s</dd>
  74. <dt>%s</dt><dd>%s</dd>
  75. </dl>
  76. </div>
  77. """ % ('Company', base_field_instance.company,
  78. 'Email', base_field_instance.email,
  79. )
  80. def queryset(self, instance):
  81. """
  82. Returns the QuerySet populating the base field. If either of the
  83. trigger_fields is None, this function will not be called.
  84. - instance: A partial instance of the parent model loaded from the
  85. request.
  86. """
  87. company = instance.client.company
  88. return CompanyContactPerson.objects.filter(company=company)
  89. def empty_choices_text(self, instance):
  90. """
  91. If either of the trigger_fields is None this function will be called
  92. to get the text for the empty choice in the select box of the base
  93. field.
  94. - instance: A partial instance of the parent model loaded from the
  95. request.
  96. """
  97. return "Please update the client field"
  98. class CaseAdmin(admin.ModelAdmin):
  99. def formfield_for_foreignkey(self, db_field, request, **kwargs):
  100. """
  101. Alters the widget displayed for the base field.
  102. """
  103. if db_field.name == "company_contact_person":
  104. kwargs['widget'] = CompanyContactPersonWidget(
  105. base_field=db_field,
  106. modeladmin=self,
  107. request=request,
  108. )
  109. kwargs['label'] = 'Contact'
  110. return super(CaseAdmin, self).formfield_for_foreignkey(db_field,
  111. request, **kwargs)
  112. class ClientAdmin(admin.ModelAdmin):
  113. pass
  114. class CompanyContactPersonAdmin(admin.ModelAdmin):
  115. pass
  116. class CompanyAdmin(admin.ModelAdmin):
  117. pass
  118. admin.site.register(Case, CaseAdmin)
  119. admin.site.register(Client, ClientAdmin)
  120. admin.site.register(CompanyContactPerson, CompanyContactPersonAdmin)
  121. admin.site.register(Company, CompanyAdmin)
  122. ```
  123. ## Installation ##
  124. sudo pip install django-admin-flexselect
  125. ## Configuration ##
  126. 1. Add `"flexselect",` to `INSTALLED_APPS` in "settings.py".
  127. 2. Add `(r'^flexselect/', include('flexselect.urls')),` to "urls.py".
  128. ### Options ###
  129. As of yet, flexselect only have one configuration option, namely
  130. "include_jquery" that if set to true will include jQuery and jQueryUI from
  131. the google ajax CDN. It defaults to false and the entire FLEXSELECT dict can
  132. be omitted.
  133. ```python
  134. # Flexselect settings.
  135. FLEXSELECT = {
  136. 'include_jquery': True,
  137. }
  138. ```
  139. ### Static files ###
  140. FlexSelect requires "django.contrib.staticfiles" installed to work
  141. out of the box. If it is not then include "jQuery", "jQueryUI" and
  142. "flexselect/static/flexselect/js/flexselect.js" manually. Read more about
  143. "django.contrib.staticfiles" at
  144. https://docs.djangoproject.com/en/1.3/ref/contrib/staticfiles/.