Это сводит меня с ума и пугает меня примерно в той же степени.
У меня есть страница регистрации здесь: http://eatfeastly.com (я перезапустил сервер в полночь 15 августа, что временно устраняет проблему, поэтому вам, возможно, придется подождать, чтобы увидеть проблему)
Вы заметите, что в нем уже предварительно заполнена электронная почта некоторого пользователя. Обратите внимание, что это означает, что эти данные находятся не только в моем кеше. Само собой разумеется, что это ПЛОХО для наших пользователей.
Я использую для этого следующий MVT:
Модель
class PotentialUser(CommonInfo):
is_cook = models.BooleanField()
email = models.EmailField(unique=True, db_index=True, validators=[validate_no_existing_user_email])
location = models.CharField(max_length=500, help_text="Please enter city, state.")
zipcode = models.CharField(max_length=10, blank=True)
class LOCATION:
DC = "Washington, DC"
NY = "New York City, NY"
SF = "San Francisco, CA"
OTHER = "Other"
def __unicode__(self):
return self.email
def send_signup_email(self):
# Can't use django notifications here, since it requires an actual user, and this is only a potential user
msg = MultipartTemplateEmailMessage('signup_complete',
from_email=settings.DEFAULT_FROM_EMAIL,
to=[self.email],
part_templates=(
('full.txt', 'text/plain'),
),
context={
'recipient': self,
'support_email': settings.SUPPORT_EMAIL,
# shortened from:
# http://eatfeastly.com/?utm_source=cont-e-pot&utm_medium=email-auto&utm_content=feedme&utm_campaign=e-share
'share_url': "http://goo.gl/X2VtA",
},
)
msg.send()
Форма
class PotentialUserModelForm(forms.ModelForm):
# Override to make this field required
is_cook = forms.TypedChoiceField(
required=True,
coerce=bool,
choices=(
('cook', True),
('feaster', False),
('both', True),
)
)
class Meta:
model = PotentialUser
def clean(self):
cleaned_data = super(PotentialUserModelForm, self).clean()
location = cleaned_data.get('location')
if location == "Other":
zipcode = cleaned_data.get('zipcode')
if zipcode is None or zipcode == '':
if not 'zipcode' in self._errors:
self._errors['zipcode'] = ErrorList()
self._errors['zipcode'].append("Zipcode is required")
del cleaned_data['zipcode']
return cleaned_data
Вид
class PotentialUserCreateView(CreateView):
form_class = PotentialUserModelForm
template_name = "intro/home.html"
form_focused = False
def get_success_url(self):
return reverse_lazy('potential_user_thanks', self.object.pk)
def get_context_data(self, **kwargs):
kwargs['LOCATION'] = PotentialUser.LOCATION
if self.form_focused or hasattr(kwargs['form'], 'errors') and kwargs['form'].errors:
kwargs['form_focused'] = True
else:
kwargs['form_focused'] = False
return super(PotentialUserCreateView, self).get_context_data(**kwargs)
def form_valid(self, form):
# Save the user to the database and set self.object
response = super(PotentialUserCreateView, self).form_valid(form)
self.object.send_signup_email()
return response
Шаблон
<!-- ... -->
<form id="intro_form" action="{% url signup %}" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div id="intro_form_box" class="vcenter_outer">
<div class="field_container">
{{ form.email.errors }}
<label for="email">Email</label>
<input id="email" name="email" type="text" placeholder="[email protected]"
value="{{ form.email.value|default_if_none:'' }}"/>
</div>
<div class="field_container">
{{ form.is_cook.errors }}
<span>I'm a</span>
<input type="radio" id="cook_button" class="form_button" name="is_cook"
{% if form.is_cook.value == 'cook' %}checked="checked"{% endif %} value="cook"/>
<label for="cook_button">Cook</label>
<input type="radio" id="feaster_button" class="form_button" name="is_cook"
{% if form.is_cook.value == 'feaster' %}checked="checked"{% endif %} value="feaster"/>
<label for="feaster_button">Feaster</label>
<input type="radio" id="both_button" class="form_button" name="is_cook"
{% if form.is_cook.value == 'both' %}checked="checked"{% endif %} value="both"/>
<label for="both_button">Both</label>
</div>
<div class="field_container">
{{ form.location.errors }}
<span>from</span>
{# These location values should match the Area values in the database #}
<input type="radio" id="dc_button" class="form_button" name="location"
{% if form.location.value == LOCATION.DC %}checked="checked"{% endif %} value="{{ LOCATION.DC }}"/>
<label for="dc_button">{{ LOCATION.DC }}</label>
<input type="radio" id="ny_button" class="form_button" name="location"
{% if form.location.value == LOCATION.NY %}checked="checked"{% endif %} value="{{ LOCATION.NY }}"/>
<label for="ny_button">{{ LOCATION.NY }}</label>
<input type="radio" id="sf_button" class="form_button" name="location"
{% if form.location.value == LOCATION.SF %}checked="checked"{% endif %} value="{{ LOCATION.SF }}"/>
<label for="sf_button">{{ LOCATION.SF }}</label>
<input type="radio" id="other_button" class="form_button" name="location"
{% if form.location.value == LOCATION.OTHER %}checked="checked"{% endif %} value="{{ LOCATION.OTHER }}"/>
<label for="other_button">Other</label>
<div id="zipcode_container"
{# only show the container if other is checked or there are validation errors #}
{% if form.zipcode.errors %}
class="field_error"
{% else %}{% if form.location.value != LOCATION.OTHER %}
style="display:none;"
{% endif %}{% endif %}
>
<div>
<span>
Sorry Feastly only works in select cities at the moment.<br/>
<b>Enter your zip code</b> and we'll let you know when you can join!
</span>
<label>
{{ form.zipcode.errors }}
<input type="text" id="other_location" name="zipcode" maxlength="5"
value="{{ form.zipcode.value|default_if_none:'' }}"
placeholder="zip code"/>
</label>
</div>
</div>
</div>
</div>
<button id="feed_me" type="submit">Feed me!</button>
</form>
<!-- ... -->
Вот еще одна странная часть головоломки: электронные письма некоторых пользователей не имеют связанной модели PotentialUser в базе данных, а вместо этого имеют модель Django User.
А вот и кикер: этого не происходит ни на моей машине для разработки, ни в нашей промежуточной среде. Обе эти среды имеют свои собственные настройки переопределения, но они, похоже, не имеют никакого влияния. Я тестировал это только на себе.
Однако что, похоже, исправляет это, так это перезапуск сервера. Пока что-то не происходит, либо другой пользователь входит в систему на другом компьютере, либо что-то еще (!?), и электронная почта пользователя начинает отображаться на странице регистрации.
Что может быть причиной этого? Может ли это быть утечка сеанса пользователя в другие соединения? Если да, то как это работает/происходит? И самое главное, как мне подойти к исправлению этого?
Спасибо!