Pergunta

Como posso usar o bacana JavaScript data e hora widgets que o padrão de administração do usa com o meu modo de exibição personalizado?

Eu olhei através o Django formas de documentação, e ele menciona brevemente o django.contrib.de administração.widgets, mas não sei como usá-lo?

Aqui é o meu modelo que eu quero é aplicada.

<form action="." method="POST">
    <table>
        {% for f in form %}
           <tr> <td> {{ f.name }}</td> <td>{{ f }}</td> </tr>
        {% endfor %}
    </table>
    <input type="submit" name="submit" value="Add Product">
</form>

Também, eu acho que ele deve ser notado que eu não tenha realmente escrito vista até mim dessa forma, eu estou usando uma visão genérica.Aqui é a entrada do url.py:

(r'^admin/products/add/$', create_object, {'model': Product, 'post_save_redirect': ''}),

E eu sou de pertinência de novo a todo o Django/MVC/MTV coisa, então por favor, vá fácil...

Foi útil?

Solução

A crescente complexidade da resposta ao longo do tempo, e a muitos hacks necessários, provavelmente deve adverti-lo contra a fazer isso.É confiar sem detalhes de implementação internos da administração, é provável que quebrar novamente em futuras versões do Django, e não é mais fácil de implementar do que apenas encontrar outro JS widget de calendário e usar.

Dito isto, aqui está o que você precisa fazer se você está determinado a fazer este trabalho:

  1. Definir o seu próprio ModelForm subclasse para o seu modelo (melhor para colocá-lo em forms.py na sua aplicação), e diga a ele para usar AdminDateWidget / AdminTimeWidget / AdminSplitDateTime (substitua "mydate", etc., com a devida nomes de campo a partir do seu modelo):

    from django import forms
    from my_app.models import Product
    from django.contrib.admin import widgets                                       
    
    class ProductForm(forms.ModelForm):
        class Meta:
            model = Product
        def __init__(self, *args, **kwargs):
            super(ProductForm, self).__init__(*args, **kwargs)
            self.fields['mydate'].widget = widgets.AdminDateWidget()
            self.fields['mytime'].widget = widgets.AdminTimeWidget()
            self.fields['mydatetime'].widget = widgets.AdminSplitDateTime()
    
  2. Alterar o seu URLconf para passar 'form_class':ProductForm ' em vez de 'modelo':Produto genérico create_object vista (que significa "a partir de minha_app.formulários de importação ProductForm" em vez de "de minha_app.os modelos de Produto de importação", é claro).

  3. Na cabeça de seu modelo, incluem {{ formulário.media }} a saída de links para os arquivos Javascript.

  4. E o hacky parte:a administração de data/hora widgets presumir que o i18n JS coisas tem sido carregado e, ainda, exigir core.js, mas não fornecer um automaticamente.Assim, no modelo acima {{ formulário.media }} você vai precisar de:

    <script type="text/javascript" src="/my_admin/jsi18n/"></script>
    <script type="text/javascript" src="/media/admin/js/core.js"></script>
    

    Você também pode desejar usar o seguinte admin CSS (graças Alex por mencionar isso):

    <link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>
    

Isto implica que o Django admin media (ADMIN_MEDIA_PREFIX) está em /media/admin/ - você pode alterar essa configuração.O ideal é que você use um contexto de processador para passar estes valores para o seu modelo em vez de codificar, mas que está fora do escopo desta questão.

Isso também requer que a URL /my_admin/jsi18n/ ser manualmente com cópia para o django.pontos de vista.i18n.javascript_catalog vista (ou null_javascript_catalog se você não estiver usando I18N).Você tem que fazer isso por si mesmo em vez de ir através da aplicação de administrador portanto, é acessível, independentemente de se você está logado no admin (graças Jeremy para apontar isto).Código de exemplo para o seu URLconf:

(r'^my_admin/jsi18n', 'django.views.i18n.javascript_catalog'),

Por fim, se você estiver usando o Django 1.2 ou posterior, você precisa de algum código adicional no seu modelo para ajudar os widgets encontrar os seus meios de comunicação:

{% load adminmedia %} /* At the top of the template. */

/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>

Obrigado lupefiasco para este acréscimo.

Outras dicas

Como a solução é hackish, eu acho que usar o seu próprio data/hora widget com um pouco de JavaScript, é mais viável.

Sim, acabei substituindo o /admin/jsi18n/ url.

Aqui está o que eu adicionei no meu urls.py.Certifique-se de que é acima de /admin/ url

    (r'^admin/jsi18n', i18n_javascript),

E aqui está o i18n_javascript função que eu criei.

from django.contrib import admin
def i18n_javascript(request):
  return admin.site.i18n_javascript(request)

Minha cabeça de código para a versão 1.4(alguns novos e alguns removidos)

{% block extrahead %}

<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/widgets.css"/>

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/core.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.init.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/actions.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/calendar.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/DateTimeShortcuts.js"></script>

{% endblock %}

Eu me encontrar referência a este post de um monte, e descobriu que a documentação define um um pouco menos hacky forma para substituir widgets padrão.

(Não há necessidade de substituir o ModelForm s __init__ método)

No entanto, você ainda precisará conectar seu JS e CSS de forma adequada como Carl menciona.

forms.py

from django import forms
from my_app.models import Product
from django.contrib.admin import widgets                                       


class ProductForm(forms.ModelForm):
    mydate = forms.DateField(widget=widgets.AdminDateWidget)
    mytime = forms.TimeField(widget=widgets.AdminTimeWidget)
    mydatetime = forms.SplitDateTimeField(widget=widgets.AdminSplitDateTime)

    class Meta:
        model = Product

Referência Tipos De Campo para encontrar o padrão de campos de formulário.

Começando em Django 1.2 RC1, se você estiver usando o Django admin selecionador de data widge truque, o seguinte tem de ser adicionada ao modelo, ou você verá o ícone de calendário de url a ser referenciado através de "falta-admin-media-prefixo/".

{% load adminmedia %} /* At the top of the template. */

/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>

Complementando a resposta por Carl Meyer, que eu gostaria de comentar que você precisa para colocar o cabeçalho em alguns válido bloco (no cabeçalho) dentro de seu modelo.

{% block extra_head %}

<link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
<script type="text/javascript" src="/media/admin/js/admin/RelatedObjectLookups.js"></script>

{{ form.media }}

{% endblock %}

Abaixo também funciona como um último recurso, caso o acima falhou

class PaymentsForm(forms.ModelForm):
    class Meta:
        model = Payments

    def __init__(self, *args, **kwargs):
        super(PaymentsForm, self).__init__(*args, **kwargs)
        self.fields['date'].widget = SelectDateWidget()

Mesmo como

class PaymentsForm(forms.ModelForm):
    date = forms.DateField(widget=SelectDateWidget())

    class Meta:
        model = Payments

coloque isso no seu forms.py from django.forms.extras.widgets import SelectDateWidget

Que sobre apenas atribuindo uma classe para o seu widget e, em seguida, vincular a essa classe para o datepicker do JQuery?

Django forms.py:

class MyForm(forms.ModelForm):

  class Meta:
    model = MyModel

  def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['my_date_field'].widget.attrs['class'] = 'datepicker'

E um pouco de JavaScript para o modelo:

  $(".datepicker").datepicker();

Para Django >= 2.0

Nota:Usando o administrador de widgets para a data-campos de tempo não é uma boa idéia de como administrador folhas de estilo podem entrar em conflito com o seu site folhas de estilo em caso de você estiver usando o bootstrap ou qualquer outro CSS frameworks.Se estiver a construir o seu site no bootstrap usar meu bootstrap-selecionador de data widget django-bootstrap-selecionador de data-plus.

Passo 1: Adicionar javascript-catalog URL do seu projeto (não do aplicativo) urls.py arquivo.

from django.views.i18n import JavaScriptCatalog

urlpatterns = [
    path('jsi18n', JavaScriptCatalog.as_view(), name='javascript-catalog'),
]

Passo 2: Adicionar necessário JavaScript/CSS recursos para o seu modelo.

<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script type="text/javascript" src="{% static '/admin/js/core.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static '/admin/css/widgets.css' %}">
<style>.calendar>table>caption{caption-side:unset}</style><!--caption fix for bootstrap4-->
{{ form.media }}        {# Form required JS and CSS #}

Passo 3: Use admin widgets para a data e hora campos de entrada na forms.py.

from django.contrib.admin import widgets
from .models import Product

class ProductCreateForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'publish_date', 'publish_time', 'publish_datetime']
        widgets = {
            'publish_date': widgets.AdminDateWidget,
            'publish_time': widgets.AdminTimeWidget,
            'publish_datetime': widgets.AdminSplitDateTime,
        }

Atualizado solução e a solução para SplitDateTime com required=False:

forms.py

from django import forms

class SplitDateTimeJSField(forms.SplitDateTimeField):
    def __init__(self, *args, **kwargs):
        super(SplitDateTimeJSField, self).__init__(*args, **kwargs)
        self.widget.widgets[0].attrs = {'class': 'vDateField'}
        self.widget.widgets[1].attrs = {'class': 'vTimeField'}  


class AnyFormOrModelForm(forms.Form):
    date = forms.DateField(widget=forms.TextInput(attrs={'class':'vDateField'}))
    time = forms.TimeField(widget=forms.TextInput(attrs={'class':'vTimeField'}))
    timestamp = SplitDateTimeJSField(required=False,)

form.html

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/admin_media/js/core.js"></script>
<script type="text/javascript" src="/admin_media/js/calendar.js"></script>
<script type="text/javascript" src="/admin_media/js/admin/DateTimeShortcuts.js"></script>

urls.py

(r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),

Eu uso esse, é ótimo, mas tenho 2 problemas com o modelo:

  1. Eu vejo os ícones do calendário duas vezes para cada apresentado no modelo.
  2. E por Hora eu tenho 'Introduza uma data válida.'

    Here is a screenshot of the Form

models.py

from django.db import models
    name=models.CharField(max_length=100)
    create_date=models.DateField(blank=True)
    start_time=models.TimeField(blank=False)
    end_time=models.TimeField(blank=False)

forms.py

from django import forms
from .models import Guide
from django.contrib.admin import widgets

class GuideForm(forms.ModelForm):
    start_time = forms.DateField(widget=widgets.AdminTimeWidget)
    end_time = forms.DateField(widget=widgets.AdminTimeWidget)
    create_date = forms.DateField(widget=widgets.AdminDateWidget)
    class Meta:
        model=Guide
        fields=['name','categorie','thumb']

Em Django 10.myproject/urls.py:no início de urlpatterns

  from django.views.i18n import JavaScriptCatalog

urlpatterns = [
    url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'),
.
.
.]

No meu template.html:

{% load staticfiles %}

    <script src="{% static "js/jquery-2.2.3.min.js" %}"></script>
    <script src="{% static "js/bootstrap.min.js" %}"></script>
    {# Loading internazionalization for js #}
    {% load i18n admin_modify %}
    <script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/jquery.init.js" %}"></script>

    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/base.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/forms.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/login.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/widgets.css" %}">



    <script type="text/javascript" src="{% static "/admin/js/core.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/SelectFilter2.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/admin/RelatedObjectLookups.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/actions.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/calendar.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/admin/DateTimeShortcuts.js" %}"></script>

A Minha Instalação Do Django :1.11 Bootstrap:3.3.7

Como nenhuma das respostas são completamente claro, estou a partilhar a minha código de modelo que apresenta nenhum erro em tudo.

Metade superior do modelo:

{% extends 'base.html' %}
{% load static %}
{% load i18n %}

{% block head %}
    <title>Add Interview</title>
{% endblock %}

{% block content %}

<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>

Metade Inferior:

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/actions.min.js' %}"></script>
{% endblock %}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top