これは私の心を吹き飛ばし、ほぼ同じ程度に私を驚かせています.
ここにサインアップ ページがあります: http://eatfeastly.com (8 月 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="yourname@domain.com"
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>
<!-- ... -->
これはパズルのもう 1 つの奇妙なピースです。一部のユーザーの電子メールには、データベースに関連付けられた PotentialUser モデルがなく、代わりに Django User モデルがあります。
私の開発マシンでも、ステージング環境でも発生しません。これらの環境には両方とも独自のオーバーライド設定がありますが、それらは何の影響もないようです。私はこれを自分でテストしただけです。
ただし、それを修正しているように見えるのは、サーバーを再起動することです。何かが起こるまで、別のユーザーが別のコンピューターにログインするか何か (!?) が発生し、ユーザーの電子メールがサインアップ ページに表示されるようになります。
何が原因でしょうか? これは、ユーザーのセッションが他の接続にリークしている可能性がありますか? もしそうなら、それはどのように機能しますか/起こりますか? そして最も重要なことは、これを修正するにはどうすればよいですか?
ありがとう!