Django:在 {% url } 标签中输入 UUID
Django: UUID type in {% url } tag
简介
我正在关注 Django tutorial. In contrast to it I have two databases - MySql and Cassandra. Therefore, I need to use also the Cassandra models which contain the UUID 类型。 UUID 具有 32 个字母数字字符和四个连字符 (8-4-4-12) 的形式。因此,我的 urls.py:
中有相当复杂的正则表达式
^([A-Fa-f0-9]{8}))(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12}
问题
在 polls/templates/polls/detail.html
模板中是以下行:
<form action="{% url 'polls:vote' question.question_id %}" method="post">
然后 question.question_id
的 UUID 类型被转换为:
/polls/UUID('47de663a-57f2-4ca1-9ad9-81df9ae25973')/
而不是
/polls/47de663a-57f2-4ca1-9ad9-81df9ae25973/
因此,我收到错误消息:
Reverse for 'vote' with arguments
'(UUID('47de663a-57f2-4ca1-9ad9-81df9ae25973'),)' and keyword
arguments '{}' not found. 1 pattern(s)
tried:[u'polls/(?P^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$'
问题
UUID类型如何处理?
我想我不能在 {% url}
标签中使用 str(question.question_id) 函数。
来源
根网址 - mysite/urls.py:
from django.conf.urls import url
from . import views
app_name= 'polls'
urlpatterns = [
#ex: /polls/
url(r'^$',views.index, name='index'),
#ex: /polls/uuid
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/$', views.detail, name='detail'),
#ex: /polls/uuid/results/
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/results/$', views.results, name='results'),
#ex: /polls/uuid/vote
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$', views.vote, name='vote'),
]
投票应用 polls/urls.py:
from django.conf.urls import url
from . import views
app_name= 'polls'
urlpatterns = [
url(r'^$',views.index, name='index'),
#ex: polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
#ex: /polls/5/volte
url(r'^(?P<question_id>(^([A-Fa-f0-9]{8}))(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$', views.vote, name='vote'),
#ex: polls/5/
url(r'^(?P<question_id>[^/]+)/$',views.detail, name='detail'),
]
polls/views.py:
from django.shortcuts import render
# Create your views here.
from django.shortcuts import render, get_object_or_404
from .models import Question, Choice
from django.shortcuts import get_object_or_404, render
def index(request):
#latest_question_list = Question.objects.order_by('-pub_date')[5:]
latest_question_list = Question.objects()
context = {
'latest_question_list': latest_question_list,
}
return render(request, 'polls/index.html', context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question':question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = get_object_or_404(Choice, pk=question_id)
#selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(
reverse('polls:results', args=(question.question_id,))
)
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
polls/templates/polls/detail.html:
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.question_id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
polls/Models.py:
from django.db import models
# Create your models here
import uuid
from cassandra.cqlengine import columns
from cassandra.cqlengine import models
from django_cassandra_engine.models import DjangoCassandraModel
class User(models.Model):
username = columns.Text(primary_key=True)
password = columns.Text()
email = columns.Text()
fullname = columns.Text()
is_staff = columns.Boolean(default=False)
class ExampleModel(DjangoCassandraModel):
example_id = columns.UUID(primary_key=True, default=uuid.uuid4)
example_type = columns.Integer(index=True)
created_at = columns.DateTime()
description = columns.Text(required=False)
class Question(DjangoCassandraModel):
def __str__(self):
return self.question_text
question_id = columns.UUID(primary_key=True)
question_text = columns.Text()
pub_date = columns.TimeUUID()
class Choice(DjangoCassandraModel):
def __str__(self):
return self.choise_text
question = columns.UUID(primary_key=True)
choice_text = columns.Text()
votes = columns.Integer(index=True,default=0)
您的 question_id
正则表达式是错误的。如果您使用 uuid4
就像您看起来那样(并且假设您不希望大写字母进行验证,因为 python 的 uuid.uuid4()
在呈现为字符串时会产生小写字母),则正则表达式question_id
捕获的组是:
(?P<question_id>[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})
为 Django 2.0 编辑:
Django 现在有 path converters,因此您不再需要 uuid4 正则表达式。这是一个例子:
from django.urls import path
urlpatterns = [
path('questions/<uuid:question_id>/', MyView.as_view()),
]
简介
我正在关注 Django tutorial. In contrast to it I have two databases - MySql and Cassandra. Therefore, I need to use also the Cassandra models which contain the UUID 类型。 UUID 具有 32 个字母数字字符和四个连字符 (8-4-4-12) 的形式。因此,我的 urls.py:
中有相当复杂的正则表达式^([A-Fa-f0-9]{8}))(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12}
问题
在 polls/templates/polls/detail.html
模板中是以下行:
<form action="{% url 'polls:vote' question.question_id %}" method="post">
然后 question.question_id
的 UUID 类型被转换为:
/polls/UUID('47de663a-57f2-4ca1-9ad9-81df9ae25973')/
而不是
/polls/47de663a-57f2-4ca1-9ad9-81df9ae25973/
因此,我收到错误消息:
Reverse for 'vote' with arguments '(UUID('47de663a-57f2-4ca1-9ad9-81df9ae25973'),)' and keyword arguments '{}' not found. 1 pattern(s) tried:[u'polls/(?P^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$'
问题
UUID类型如何处理?
我想我不能在 {% url}
标签中使用 str(question.question_id) 函数。
来源
根网址 - mysite/urls.py:
from django.conf.urls import url
from . import views
app_name= 'polls'
urlpatterns = [
#ex: /polls/
url(r'^$',views.index, name='index'),
#ex: /polls/uuid
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/$', views.detail, name='detail'),
#ex: /polls/uuid/results/
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/results/$', views.results, name='results'),
#ex: /polls/uuid/vote
url(r'^(?P<question_id>^([A-Fa-f0-9]{8})(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$', views.vote, name='vote'),
]
投票应用 polls/urls.py:
from django.conf.urls import url
from . import views
app_name= 'polls'
urlpatterns = [
url(r'^$',views.index, name='index'),
#ex: polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
#ex: /polls/5/volte
url(r'^(?P<question_id>(^([A-Fa-f0-9]{8}))(-[A-Fa-f0-9]{4}){3}-[A-Fa-f0-9]{12})/vote/$', views.vote, name='vote'),
#ex: polls/5/
url(r'^(?P<question_id>[^/]+)/$',views.detail, name='detail'),
]
polls/views.py:
from django.shortcuts import render
# Create your views here.
from django.shortcuts import render, get_object_or_404
from .models import Question, Choice
from django.shortcuts import get_object_or_404, render
def index(request):
#latest_question_list = Question.objects.order_by('-pub_date')[5:]
latest_question_list = Question.objects()
context = {
'latest_question_list': latest_question_list,
}
return render(request, 'polls/index.html', context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question':question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = get_object_or_404(Choice, pk=question_id)
#selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(
reverse('polls:results', args=(question.question_id,))
)
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
polls/templates/polls/detail.html:
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.question_id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
polls/Models.py:
from django.db import models
# Create your models here
import uuid
from cassandra.cqlengine import columns
from cassandra.cqlengine import models
from django_cassandra_engine.models import DjangoCassandraModel
class User(models.Model):
username = columns.Text(primary_key=True)
password = columns.Text()
email = columns.Text()
fullname = columns.Text()
is_staff = columns.Boolean(default=False)
class ExampleModel(DjangoCassandraModel):
example_id = columns.UUID(primary_key=True, default=uuid.uuid4)
example_type = columns.Integer(index=True)
created_at = columns.DateTime()
description = columns.Text(required=False)
class Question(DjangoCassandraModel):
def __str__(self):
return self.question_text
question_id = columns.UUID(primary_key=True)
question_text = columns.Text()
pub_date = columns.TimeUUID()
class Choice(DjangoCassandraModel):
def __str__(self):
return self.choise_text
question = columns.UUID(primary_key=True)
choice_text = columns.Text()
votes = columns.Integer(index=True,default=0)
您的 question_id
正则表达式是错误的。如果您使用 uuid4
就像您看起来那样(并且假设您不希望大写字母进行验证,因为 python 的 uuid.uuid4()
在呈现为字符串时会产生小写字母),则正则表达式question_id
捕获的组是:
(?P<question_id>[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})
为 Django 2.0 编辑: Django 现在有 path converters,因此您不再需要 uuid4 正则表达式。这是一个例子:
from django.urls import path
urlpatterns = [
path('questions/<uuid:question_id>/', MyView.as_view()),
]