æšæºããŒã«ããã¯ã¹ã¯ãPostgreSQLãDjango 1.4ïŒ+ GeoDjangoïŒãSentryãCeleryïŒ+ redisïŒãFabricã§ãã
ã¹ã¿ãŒãããŒãž

ã¹ã¿ãŒãããŒãžã«ç°åžžãªãã®ã¯ãããŸããïŒç»é²ãã©ãŒã ã ç§ããã§ã«æžããããã«ããã¥ãŒãã©ãŒã ã¯èªäœã§ããããããããã¥ãŒããã©ãŒã ã䜿çšããŠããªãããšã«æ°ä»ããåŸããžã£ã³ãŽç»é²ã¯inããã«åãåããŸãããã¢ãã«ãèªåŒããããšããŠãããžã§ã¯ãã®ãã°ãã©ãã«ãŒãç¡å¹ã«ãªããŸãã:)
ç»é²ãããšãæšæ¶ç¶ãéä¿¡ãããhtmlãšããŠäœæãããŸãã html-letterãéä¿¡ããã«ã¯ã templated-emailsã䜿çšããŸãããã³ãã¬ãŒãã«ã¯ããã¹ãŠã®æåãä¿åãããemailsãã©ã«ããŒããããŸãã åã¬ã¿ãŒã¯ãemail.htmlïŒã¬ã¿ãŒã®htmlããŒãžã§ã³ïŒãemail.txtïŒã¬ã¿ãŒã®ããã¹ãããŒãžã§ã³ïŒãããã³short.txtïŒä»¶åïŒã®3ã€ã®ãã¡ã€ã«ãå«ãç¬èªã®ãã©ã«ããŒã«ãããŸãã

æçŽã¯æ¬¡ã®ããã«éãããŸãã
send_templated_email([user], 'emails/activation', context=context)
åä¿¡è ã®ãªã¹ãã«ãŠãŒã¶ãŒãŸãã¯é»åã¡ãŒã«ã¢ãã¬ã¹ãéä¿¡ã§ããŸãã ãã³ã»ã³ã¹ã§ãããã·ã³ãã«ã§äŸ¿å©ãªãç§ãã¡ã¯ããªãé·ãéãããŸããŸãªãããžã§ã¯ãã§ãã®ã¢ãããŒãã䜿çšããŠããŸãã
html-letterã«ã¯ãã1ã€ã®åé¡ããããŸã-éçºäžã«ããããã©ã®ããã«èŠãã°èªåã«çµ¶ããéä¿¡ãããã¯ããŸãæ確ã§ã¯ãããŸããã ããŒã«ã«ã§ç¢ºèªããã«ã¯ã django-eml-email-backend ïŒéä¿¡ãã代ããã«emlãã¡ã€ã«ã«æåãä¿åããé»åã¡ãŒã«ããã¯ãšã³ããåãããã ã¢ããªã±ãŒã·ã§ã³ïŒã䜿çšããŸãã ã»ãšãã©ã®ã¡ãŒã«ã¯ã©ã€ã¢ã³ãã¯åé¡ãªãemlãã¡ã€ã«ãéããŸãïŒã¹ããŒã¹ã«ãã£ãŠããããã¢ããã®ãã¬ãã¥ãŒããããŸãïŒã
ããããŸãããã¶ã¬ã®ã¹
ã¢ã«ãŠã³ããç»é²ããŠèšå®ãããšããŠãŒã¶ãŒã¯ã¡ã€ã³ããŒãžã«ç§»åããŸãã

ãã®äžã§ãæ€çŽ¢ãã©ãŒã ã«æ³šæãæãããšãã§ããŸãã

èŠçŽ ã¯ããšããšæ¬¡ã®ããã«ã¬ã€ã¢ãŠããããŠããŸããã
<div class="b-filter_selector time"> <select name="persons" data-behavior="Chosen"> <option value="1">1 </option> <option value="2" selected="selected>2 </option> <option value="3">3 </option> </select> </div>
é£äžã¯BEMã«åºå·ããããšããŸãããå ¥åã¯ãã°ãã°divã«ã©ããããããã°ãã°cssã¯ã©ã¹ãããŒã¿å±æ§ãªã©ãå±æ§ä»ãããå¿ èŠããããŸãã
Pythonã³ãŒãã§htmlãçž«ãã®ã¯æªãå³ã§ããhtmlã¯ãã³ãã¬ãŒãã«ããã¹ãã§ãã jungå ã®ãã³ãã¬ãŒãå ã®ãã©ãŒã èŠçŽ ã®ã¬ã³ããªã³ã°ã«åœ±é¿ãäžããéåžžã®çµã¿èŸŒã¿ããŒã«ã¯ãããŸããïŒããã§ã¯ããã£ãŒã«ãã«ããŒã¿ã®æ¯ãèããè¿œå ããå¿ èŠããããŸãïŒã ãã®ãããªããšãããã¬ã€ã¢ãŠãããã蟌ããšãã«django-widget- tweaks ïŒ bitbucket ã github ïŒãéåžžã«ç©æ¥µçã«äœ¿çšããŠããããããã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã蟌ã¿ããã»ã¹ãç°¡çŽ åããŠããŒãã«ã§ããŸãã
<div class="b-filter_selector time"> {% render_field search_form.persons data-behavior='Chosen' %} </div>
ãã£ãŒã«ãã«äœããã®çš®é¡ã®æšæºãã€ã³ãã£ã³ã°ãå¿ èŠãªå Žåãhtmlã¹ãããããäœæãã{ïŒ includeïŒ }ïŒæ¬¡ã®ãããªãã®ïŒãä»ããŠæ¥ç¶ã§ããŸãã
{% comment %} : {% include "inc/input.html" with field=form.query div_classes="search" no_label=0 %} {% endcomment %} {% load widget_tweaks %} {% if no_label != 1 %}{{ field.label_tag }}{% endif %} <div class="b-input {{ div_classes }} {% if field.errors %}error{% endif %}"> {{ field|add_class:'b-input_input' }} </div>
ãšã©ãŒåºåã«ã€ããŠãåãããšãèšããŸãã
django-widget-
{% render_field %}
ã¯ãæ¢åã®å±æ§ã«å±æ§ïŒcssã¯ã©ã¹ãªã©ïŒãè¿œå ããããšãã§ããŸãã
{% render_field form.emails rows="2" class+="b-input_textarea gray" autofocus="" %} {% include "inc/errors.html" with errors=form.emails.errors %}
å©çšå¯èœãªä»æ¥ãããã¯

ãã®ãããã¯ã«ã¯ãä»æ¥äºçŽå¯èœãª5ã€ã®ã¬ã¹ãã©ã³ããããŸãã 圌ãã¯æ¬¡ã®ããã«ãªããŸãïŒ
restaurants = Restaurant.objects.enabled().free_today_in_city(city).prefetch_related('scenes')[:5]
ã芧ã®ãšããããã®ã¡ãœããã®ãã§ãŒã³ã¯ããã§æ§ç¯ãããŸãïŒ
.enabled().free_today_in_city(city)
ïŒã çµã¿èŸŒã¿ã®dzhangovskyã¢ãããŒã-ãã®ãããªããŒã¹ããããŒãžã£ã«æž¡ã-ã¯ããããèš±å¯ããŸããã ãããŒãžã£ãŒã¡ãœããã¯ãã«ã¹ã¿ã ã¡ãœãããæ¢ã«æããªãQuerySetãè¿ããŸãããã£ã«ã¿ãªã³ã°ã®ããã«ã䜿çšã§ããã¡ãœããã¯1ã€ã ãã§ãã
ãã®å¶éãåé¿ããã«ã¯ã django-model-utilsã® PassThroughManagerã䜿çšããŠããããŒãžã£ãŒã§ã¯ãªãQuerySetãèšè¿°ããŸãã
class RestaurantQueryset(QuerySet): def enabled(self): return self.filter(enabled=True) def free_today_in_city(self, city): today = city.now().date() return self.filter(city=city).free(today) def free(self, date): # ... class Restaurant(models.Model): # ... objects = PassThroughManager.for_queryset_class(RestaurantQueryset)()
ãã®ãããªãã¹ããã€ãã®ç®¡çè ããåŸãããŸãïŒç§ã¯åçãéžã°ãªãããšã«æ±ºããŸãã:)ïŒã æšæºãããŒãžã£ãŒã®ä»£ããã«ãããžã§ã¯ãå šäœã§äœ¿çšããŸãã
ããã¹ãŠè¡šç€ºããã¯ãªãã¯ããŸã
...ãããŠãã¬ã¹ãã©ã³ã®ãªã¹ããå«ãããŒãžã«ç§»åããŸãã ãã®ããŒãžã¯çŽ æŽãããæ€çŽ¢ãã©ãŒã ã§ãããçµæã¯Ajaxã«ãã£ãŠæŽæ°ãããŸãã

ç§ã¯jsã«ã€ããŠå°ããªå人çãªãæµè¡ããæã£ãŠããŸãïŒãµã€ãã¯jsãªãã§äœ¿çšã§ããã¯ãã§ãã ããã«ãããéçºæã«ããã€ãã®å©ç¹ãåŸãããŸãã æãããªãã®ã«å ããŠïŒjsã®ãšã©ãŒã¯ãµã€ããåäœäžèœã«ããŸããïŒãããšãã°ããã®ãããªãµã€ãã¯ãã¹ããç°¡åã§ãïŒã»ã¬ã³ãªãã§æã確èªã§ããŸãïŒ+æžãããããããããŸãã
çŸæç¹ã§ã¯ãajaxã«æ¬¡ã®ã¢ãããŒãã䜿çšããŸããajaxãšéåžžã®ãªã¯ãšã¹ãã¯åããã¥ãŒã§åŠçãããŸããå¯äžã®éãã¯ãã³ãã¬ãŒãã«ãããŸãã ãªããªã ajaxãã³ãã¬ãŒãã¯éåžžã®ãã³ãã¬ãŒãã®äžéšã§ãããããéåžžã®ãã³ãã¬ãŒãã«æ¥ç¶ããŸãã éåžžã®ãã¿ãŒã³ïŒ
{% extends 'base.html' %} <!-- : , --> ... <div class="b-search-results_result"> {% include 'restaurants/ajax/list.html' %} </div> ... <!-- : , -->
Ajaxãã¿ãŒã³ïŒ
<ul class="b-search-results_result_list"> {% for restaurant in restaurants %} <li>...</li> {% endfor %} </ul>
ãã³ãã¬ãŒãã¯request.is_ajaxïŒïŒã«åºã¥ããŠéžæãããŸãã ã¯ã©ã€ã¢ã³ãã«ã¯å®£èšçãªjsããããéåžžã®htmlãã©ãŒã ãajaxã«å€æã§ããŸãã
def restaurant_list(request, city_slug): # ... response = TemplateResponse(request, 'restaurants/list.html', {...}) if request.is_ajax(): response.template_name = 'restaurants/ajax/list.html' return response
PanGurmanã§ã¯ããããå°ãå®éšããããšã«ããŸããã æåã¯@ajax_templateãã³ã¬ãŒã¿ã§ããã¥ãŒã«ajaxãè¿œå ããŸããã
@ajax_template('restaurants/ajax/list.html') def restaurant_list(request, city_slug): # ... return TemplateResponse(request, 'restaurants/list.html', {...})
ã€ãŸã ãã³ã¬ãŒã¿ã§éåžžã®ãã¥ãŒãã©ããããããŒã¿å±æ§ããã©ãŒã ã«æžã蟌ããšããã©ãŒã ãajaxã«ãªããŸãã
ãããããã®ãªãã·ã§ã³ã¯
'restaurants/(ajax/)?list.html'
ïŒããã¯
'restaurants/(ajax/)?list.html'
ããšã©ãŒã®åå ã§ãïŒãç¹°ãè¿ããŸã
'restaurants/(ajax/)?list.html'
+ãã¥ãŒã«ã¯ããã€ãã®æ»ãç¹ãããããã¹ãŠãajaxã§è¡ãå¿ èŠã¯ãããŸããïŒã€ãŸãããªãã·ã§ã³ã¯åçŽãªãã§ãã¯ãããæªãã§ããã³ã¬ãŒã¿ïŒã
ãããã£ãŠã圌ãã¯@ajax_templateãæåŠãããããŸã§ã®ãšãããã®ãªãã·ã§ã³ã決å®ããŠããŸãã
def restaurant_list(request, city_slug): # ... return show(request, 'restaurants/list.html', {...})
showã¯TemplateResponseã®åå«ã§ãããajaxãªã¯ãšã¹ãã®å Žåãæåã«ajaxãµããã©ã«ããŒã§ãã³ãã¬ãŒããè©Šè¡ããŸãã https://gist.github.com/2416695ãåç §ããŠãã ãã
ã·ã§ãŒã«ã¯ãç§ããã€ãèŠéããŠãããã2ã€ã®æ¹æ³ããããŸãã ããã«ã¯ããã€ãã®åŸ®åŠãªç¹ãããããã¹ãŠãçŽ æŽãããããã§ã¯ãããŸããïŒããšãã°ãåã®ãã¥ãŒããªãã€ã¬ã¯ããè¿ããå Žåã.with_contextã¯èœã¡ãã§ãããïŒããããã䜿çšããããšã¯ããªãå¯èœã§ãïŒãããŠåé¡ã¯ajaxãšã¯ã»ãšãã©é¢ä¿ãããŸããïŒã
ã€ãŸããAjaxãååšããªããã®ããã«ãµã€ããäœæããå¿ èŠã«å¿ããŠãã³ãã¬ãŒãã®å¿ èŠãªéšåããµããã©ã«ããŒã«å ¥ããŠåŸã§è¿œå ããŸãã
äœããèŠã€ãããã¬ã¹ãã©ã³ã§çªã
ã¬ã¹ãã©ã³ã®ããŒãžã«è¡ããŸãã

ãŸããajaxããããŸãïŒæ³šæãã©ãŒã ã§ã¯ãå©çšå¯èœãªæéã¯ajax-requestsã«ãã£ãŠãã§ãã¯ãããŸãïŒããå¥ã®æ¹æ³ã§å®è£ ãããŸã:)
ã«ã¬ã³ããŒã¯ã¯ã©ã€ã¢ã³ãäžã«æ§ç¯ãããããïŒjsããªãå Žåã¯éåžžã®å ¥åãã£ãŒã«ãããããŸãïŒããµãŒããŒããhtmlã§ã¯ãªãjsonãååŸããæ¹ãç°¡åã§ãã django-tastypieã®å©ããåããŠãç§ã¯ããã«APIãæ§ç¯ãããããéããŠjsonã¯ç®çã®APIã«æž¡ãããŸãã ããã¯ãjsonãæã§è¡šç€ºãããã¥ãŒãèšè¿°ãããããé·ãã¯ãããŸãããããšã«ããAPIã䟿å©ã«ãªããã¹ãããã«ãåºå圢åŒãªã©ã®ããŸããŸãªå©ç¹ãåŸãããŸãã
å¥ã®ãããžã§ã¯ãã§ã¯ãAPIã«django-pistonã䜿çšããŸããã 䞻芳çã«-django-tastypieã®æ¹ãããã§ãã
ãã®ãããªãã¥ãŒã«ãã£ãŠãAPIã®éåžžã«åå§çãªïŒå®å šã§ã¯ãªãïŒãã«ããèªåçã«çæãããŸãã
def _api_resources(api): resources = {} api_name = api.api_name for name in sorted(api._registry.keys()): resource = api._registry[name] resources[name] = { 'list_endpoint': api._build_reverse_url("api_dispatch_list", kwargs={ 'api_name': api_name, 'resource_name': name, }), 'schema': api._build_reverse_url("api_get_schema", kwargs={ 'api_name': api_name, 'resource_name': name, }), 'doc': resource.__doc__, 'resource': resource } return resources def browse(request, api): resources = _api_resources(api) return TemplateResponse(request, 'tasty_browser/index.html', { 'api': api, 'resources': resources })
ãã³ãã¬ãŒãïŒ
<h1>API {{ api.api_name }}</h1> <table class='tastypie-api'> <tr><th>Resource</th><th>url</th><th>Structure</th><th>Description</th></tr> {% for name, resource in resources.items %} <tr> <td>{{ name }}</td> <td> <a href='{{ resource.list_endpoint }}?format=json'> {{ resource.list_endpoint }}</a> </td> <td> <a href='{{ resource.schema }}?format=json'> {{ resource.schema }}</a> </td> <td> {{ resource.doc }} </td> </tr> {% endfor %} </table>
ããã§èŠãããšãã§ããŸãïŒ http : //pangurman.ru/api-docs/
æ¯æãã¯django-robokassa ïŒãã®åŸããã«ãªãã·ã§ã³ãè¿œå ãããŸãïŒãäºçŽã«é¢ããSMSéç¥- ã€ã¢ãã¹ +ã»ããªãä»ããŠè¡ãããŸãã
ãã¡ã€ãã³ã¹

PanGurmanã§ã¯ããŠãŒã¶ãŒã¯è³Œå ¥ã®æ¯æãã«äœ¿çšããå人ã¢ã«ãŠã³ããæã£ãŠããŸãã ããã«ããµã®å©ããåããŠãå人ãæåŸ ããããã¢ãŒã·ã§ã³ã³ãŒããå ¥åããŠè£å ã§ããŸãã ãã®åŸãäœããã®æ¹æ³ã§ãããã«ã¡ãœãããè¿œå ãããŸãã
Fowlerãèªãã§ãç§ã¯æ°å¹Žéãå人ã¢ã«ãŠã³ããã®å®è£ ã«æ¬¡ã®ã¢ãããŒãã䜿çšããŠããŸããïŒéé¡ã¯ã©ãã«ãä¿åãããŸããïŒãã ãããã£ãã·ã¥ãããå ŽåããããŸãïŒãããŒã¿ããŒã¹ã®å人ã¢ã«ãŠã³ãã«ãã©ã³ã¶ã¯ã·ã§ã³ãä¿åããŸãã ããã«ãããæäœã®å±¥æŽãèªç¶ã«ååŸãããšã©ãŒããä¿è·ã§ããŸãã
ããšãã°ãæ¯æãã·ã¹ãã ãä»ããŠå人ãè³Œå ¥ã®æ¯æãã«äžååãªéé¡ãæ¯æãå Žåããã®éé¡ã¯æåã«å人å£åº§ã«å ¥éããã次ã«åœŒã¯åž³æ¶ããè©Šã¿ãåæ¹èšå ¥ã¯å€±æãããã®äººã¯è³Œå ¥ããã«å£åº§ã«æ®ã£ããŸãŸã«ãªããŸãã
åæ§ã®ã¢ãã«ãããããžã§ã¯ããããããžã§ã¯ããžãšããããªå€æŽã§ããŸããã
class MoneyTransfer(models.Model): PURCHASE = 'purchase' ROBOKASSA = 'robokassa' INVITE_BONUS = 'invite-bonus' REFUND = 'refund' PROMOCODE = 'promocode' TRANSFER_TYPE_CHOICES = ( (u' ', ( (PURCHASE, u' '), )), (u' ', ( (ROBOKASSA, u' '), (INVITE_BONUS, u' '), (PROMOCODE, u' '), (REFUND, u''), )), ) user = models.ForeignKey(User, verbose_name=u'') amount = models.DecimalField(u'', max_digits=10, decimal_places=2) created_at = models.DateTimeField(u'/ ', auto_now_add=True) comment = models.CharField(u'', max_length=255, blank=True, null=True) transfer_type = models.CharField(u'', max_length=20, null=True, blank=True, choices=TRANSFER_TYPE_CHOICES) content_type = models.ForeignKey(ContentType, null=True, blank=True) object_id = models.PositiveIntegerField(null=True, blank=True) reason = GenericForeignKey('content_type', 'object_id')
ããã§ã¯ãéžæè¢ãæå®ããæ¹æ³ã«æ³šæãæãããšãã§ããŸãã ããã«æžããŸãããéæ³ã®å®æ°ã¯ãªãã誀ã£ãŠinvite_bonusããŒã¿ããŒã¹ã®ä»£ããã«invite_bonusããŒã¿ããŒã¹ã«æžã蟌ãããšã¯ã§ããŸãã-MoneyTransfer.INVITE_BONUSã¯åžžã«åç¬ã§ããã誀ã£ãŠæžã蟌ãŸãããšããã«AttributeErrorã«ãªããŸãïŒãããŠãªãŒãã³ã³ããªãŒãã衚瀺ãããŸãïŒã
ããŒãã«ãäºçŽããŸããããåæ¢ããŸãããã©ã®ããã«æ©èœããŸããïŒ
ãã«ãããŒãžã«ã¢ã¯ã»ã¹ããŠãã ãã ã ããã¹ãã®äžéšã§ãããã®ããŒãžã§ã¯ãæããã«ãããã°ã©ããŒã®åå ãªãã«ç·šéè ãç·šéããæ©äŒãäžãããšããã§ãããã

djangoã«ã¯ãã®ããã®ãã©ããããŒãžããããŸãããéåžžã¯å¥ã®ã¢ãããŒãã䜿çšããŸãïŒéåžžã®ãã³ãã¬ãŒãã䜿çšããŠãã¹ãŠã®ããŒãžãéåžžã®ãã¥ãŒã«ããVCSã«ãã¹ãŠãä¿åããç·šéããå¿ èŠãããããã¹ããdjango-flatblocksã®ãããã¯ã§ããŒã¯ããŸãïŒ
<div class="b-text"> {% flatblock "how-it-works" 600 %} </div>
管çè ã®å Žåãããã¹ãã«ã«ãŒãœã«ãåããããšãç·šéãããªã³ã¯ã衚瀺ãããŸã
ïŒããã¯ããã³ãã¬ãŒãflatblocks / flatblock.htmlãèšå®ããããšã«ããè¡ãããŸãïŒïŒ
{% load url from future %} {% load markup %} {% if user.is_staff %} <div class="b-flatblock-edit"> <a class="flatblock-edit-link markitup-flatblocks-edit-icon" title = " " href='{% url "edit_flatblock" flatblock.pk %}?next={{request.path}}'> </a> {{ flatblock.content|markdown:"video" }} </div> {% else %} {{ flatblock.content|markdown:"video" }} {% endif %}
markdownã®ããŒã¯ã¢ããã¯ãããã¯ã«ä¿åãããŸããç·šéããŒãžã§ã¯ã django-markitupã®ãŠã£ãžã§ããã衚瀺ããŸãïŒãã¬ãã¥ãŒããïŒã

äžéšã®ããŒã¯ã¢ããã蚱容ããããµã€ãäžã®ãã¹ãŠã®ããã¹ãã¯ãdjango-markitupã䜿çšããŠç·šéãããŸãïŒããšãã°ãåçä»ãã®ã¬ã¹ãã©ã³ã®ã€ã³ã¹ãã¬ãŒã·ã§ã³ãåãã説æïŒã ããŒã¯ããŠã³ãã£ã«ã¿ãŒã¯ãhtmlã¿ã°ã«è§Šããªãããã«æ§æãããŠãããããå¿ èŠã«å¿ããŠãä»»æã®ããŒã¯ã¢ãããããã¹ãã«è¿œå ã§ããŸãã
ãŸããæ¡åŒµæ©èœããã蟌ãŸããŠããŸãïŒ python-markdown-video ïŒãããã«ãããyoutubeãŸãã¯vimeoãžã®ãªã³ã¯ããããªã«å€æãããŸã-å奜çãªæ¹æ³ã§ãããããoembedãä»ããŠãããè¡ãå¿ èŠããããŸãã
ã¬ã¹ãã©ã³ã®ããã«
ã¬ã¹ãã©ã³ã«ã¯ãç¹å¥ãªããã«ããããããã䜿çšããŠãåŽåæéãå¶åŸ¡ã§ããŸãïŒããŒãã«ãå©çšå¯èœãªå Žåãå©çšã§ããªãå ŽåïŒã ããã«ã¯ãAdminSiteã®å¥ã®ã€ã³ã¹ã¿ã³ã¹ãéããŠå®è£ ãããŸãã ãã¬ã¹ãã©ã³ãããŒãžã£ãŒããšããŠæå®ãããŠãããŠãŒã¶ãŒã¯ããã«ã¢ã¯ã»ã¹ã§ããŸãã 埮åŠãªç¹ã¯ããããã®ãŠãŒã¶ãŒã«is_staffãã©ã°ãä»ããªãããšã§ããããããªããšãéåžžã®ç®¡çããã«ã«ã¢ã¯ã»ã¹ã§ããŸãããããã¯æãŸãããããŸããã ãããŠ-éåžžã®ã«ã¹ã¿ã 管çããã«ã
[æŽèš]
å€ãã®å ŽåãDzhangovka管çè ã«ã¯æè»æ§ããªããªã©ãšæžãããŠããŸãã -ç§ã¯äººã ãå ·äœçã«äœãæå³ããã®ãç解ã§ããŸããã§ãã:)管çããã«ã¯CRUDãã¬ã€ã¢ãŠããããã³ãã¶ã€ã³ãããã®ãŸãŸãæäŸããŸãã æ£çµ±æŽŸã®ä»£æ¿ãšããŠã圌ãã¯éåžžãããã·ã¥ããŒããæžãããã®ããçš®ã®ãã¬ãŒã ã¯ãŒã¯ãæäŸããŸã-ããã¯CRUDã«åçŽãªãã®ã§ãããdzhangovskoy管çããã«ïŒ django-admin-tools ã nexus ïŒã®ããã®ãã¬ãŒã ã¯ãŒã¯ããããŸãã
äœããã®çš®é¡ã®çžäºäœçšãCRUDã«é©åããªãå Žå-åé¡ã¯ãããŸãããã管çé åå ã®ã©ãããã§ããã¥ãŒãèšè¿°ããŠããã«ãªã³ã¯ããããšã劚ãããã®ã¯ãããŸããïŒããã§ã¯ãreadonly_fieldsãšlist_displayã䟿å©ãªããšããããããŸã;ãã³ãã¬ãŒãããªãŒããŒã©ã€ãããããšãã§ããŸãïŒã æ°å¹Žéã欲æã®ç®¡çããã«ãæããããæžãçŽãããããããšã¯æ±ºããŠãããŸããã§ãããç§ãã¡ã¯ãã¹ãŠã®ãããžã§ã¯ãã§ããã䜿çšããå€ãã®æéãç¯çŽããŸããã ããããããããžã§ã¯ãã®è©³çŽ°ã¯ããã§ããããããšãç§ã¯æ¬åœã«æãããªäœããèŠéããŠããŸããç§ã¯ç¥ããŸããã
[æŽèš]
管çããã«ã§ã¯ãraw_id_fieldsã®ä»£ããã«ãæãããåådjango- salmonellaã®ã¢ããªã±ãŒã·ã§ã³ãç©æ¥µçã«äœ¿çšããŸããããã¯ããŠã£ãžã§ããã«ãææãããæçšãªåäœã䌎ãé¢é£ã¬ã³ãŒããéžæããŸãïŒFKããã³M2Mã®å ŽåïŒ


ãªããžã§ã¯ãã®IDã«å ããŠããã®ååã衚瀺ãããŸãïŒajaxã«ãã£ãŠæŽæ°ãããŸãïŒã ååãã¯ãªãã¯ãããšããªããžã§ã¯ããå€æŽããããŒãžã«ããã«ã¢ã¯ã»ã¹ã§ããŸããããã䟿å©ã§ãã
ãã¹ã
ãã¹ãã®ããã«ã圌ãã¯å·¥å Žã®å°å¹Ž ïŒãã©ãŒã¯ïŒã䜿ãå§ããŸããã ãã以æ¥ããã¡ã¯ããªãŒããŒã€ã«éåžžã«äŸ¿å©ãªãã®ã1ã€ç»å ŽããŸãããRelatedFactoryã§ãã SubFactoryã®ãããªãã®ã§ããã®å察ã§ãïŒããšãã°ããŠãŒã¶ãŒã®ãã¡ã¯ããªãäœæããŠãããã«ãããã¡ã€ã«ãäœæã§ããŸãïŒã ããã¥ã¡ã³ãã¯ããã§èªãããšãã§ããŸã ã äŸïŒ
class ProfileF(factory.DjangoModelFactory): FACTORY_FOR = Profile city = factory.SubFactory(CityF) balance = 0 @classmethod def _prepare(cls, create, **kwargs): # 'balance=555' balance = kwargs.pop('balance') profile = super(ProfileF, cls)._prepare(create, **kwargs) if balance > 0: MoneyTransferF(user=profile.user, amount=balance) return profile class UserF(factory.DjangoModelFactory): FACTORY_FOR = User username = factory.Sequence(lambda n: "username%s" % n) first_name = factory.Sequence(lambda n: u" %s" % n) last_name = factory.Sequence(lambda n: u" %s" % n) email = factory.Sequence(lambda n: "email%s@example.com" % n) is_staff = False is_active = False is_superuser = False password = '123' profile = factory.RelatedFactory(ProfileF, 'user') @classmethod def _prepare(cls, create, **kwargs): kwargs['password'] = make_password(kwargs['password']) return super(UserF, cls)._prepare(create, **kwargs)
ãã¹ãã§ã¯ã次ã®ããã«èšè¿°ã§ããŸãã
user = UserF(profile__balance=100)
ãŠã©ãŒã ã¢ãããšããŠã3çªç®ã®pythonã®ãµããŒããè¿œå ããŠfactory-boyã§pull-requestãè¡ããŸãããã3çªç®ã®pythonã¯å¥ã®ã¹ããŒãªãŒã®ãããã¯ã§ãïŒ
Django 1.4ã«ã¯ããã¹ãã«é¢ãããã1ã€ã®ããªãã¯ããããŸãã ããã©ã«ãã§ã¯ãPBKDF2ã¢ã«ãŽãªãºã ããã¹ã¯ãŒãã®ããã·ã¥ã«äœ¿çšãããŠããŸãã PBKDF2ã§ã¯ãã»ãã¥ãªãã£æ©èœã®1ã€ãäœéã§ãã ããããã»ãã¥ãªãã£ãšã¯å¥ã«ãäœéã¯ããã«äœéãä¿èšŒããŸã:)ã¡ã€ã³ãµã€ãã§ã¯ããã¯ãŸã£ããåé¡ã§ã¯ãããŸããïŒãŠãŒã¶ãŒã¯ãã°ã€ã³ãããã³ã«ç»é²ãããé 延ã¯å°ããã§ãïŒãããã¹ãã§ã¯ãç¹ã«å·¥å Žã䜿çšããå ŽåããããéèŠãªããšã§ããããšãå€æããŸãã-boyãšããã·ã¥ã䜿çšããŠãã¹ã¯ãŒããå²ãåœãŠãããšã«ãããå€ãã®ãŠãŒã¶ãŒãäœæããŸãã
PanGurmanã®å Žåãtest_settings.pyã«ãã®è¡ãã€ã³ã¹ããŒã«ãããšããã¹ãã2åã«å éãããŸããã
PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher']